Loading files
// Created on: 2006-04-12
// Created by: Andrey BETENEV
// Copyright (c) 2006-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <OSD_Thread.hxx>
//=============================================
// OSD_Thread::OSD_Thread
//=============================================
OSD_Thread::OSD_Thread()
: myFunc(nullptr),
myThread(OSD_PTHREAD_NULL),
myThreadId(0),
myPriority(0)
{
}
//=============================================
// OSD_Thread::OSD_Thread
//=============================================
OSD_Thread::OSD_Thread(const OSD_ThreadFunction& func)
: myFunc(func),
myThread(OSD_PTHREAD_NULL),
myThreadId(0),
myPriority(0)
{
}
//=============================================
// OSD_Thread::OSD_Thread
//=============================================
OSD_Thread::OSD_Thread(const OSD_Thread& other)
: myFunc(other.myFunc),
myThread(OSD_PTHREAD_NULL),
myThreadId(0)
{
Assign(other);
}
//=============================================
// OSD_Thread::Assign
//=============================================
void OSD_Thread::Assign(const OSD_Thread& other)
{
// copy function pointer
myFunc = other.myFunc;
myPriority = other.myPriority;
// detach current thread
Detach();
#ifdef _WIN32
// duplicate the source handle
if (other.myThread)
{
HANDLE hProc = GetCurrentProcess(); // we are always within the same process
if (!DuplicateHandle(hProc, other.myThread, hProc, &myThread, 0, TRUE, DUPLICATE_SAME_ACCESS))
{
// DuplicateHandle failed, ensure handle stays null
myThread = OSD_PTHREAD_NULL;
myThreadId = 0;
return;
}
}
#else
// On Unix/Linux, just copy the thread id
myThread = other.myThread;
#endif
myThreadId = other.myThreadId;
}
//=============================================
// OSD_Thread::~OSD_Thread
//=============================================
OSD_Thread::~OSD_Thread()
{
Detach();
}
//=============================================
// function : SetPriority
// purpose : Set the thread priority relative to the caller's priority
//=============================================
void OSD_Thread::SetPriority(const int thePriority)
{
myPriority = thePriority;
#ifdef _WIN32
if (myThread)
SetThreadPriority(myThread, thePriority);
#endif
}
//=============================================
// OSD_Thread::SetFunction
//=============================================
void OSD_Thread::SetFunction(const OSD_ThreadFunction& func)
{
// close current handle if any
Detach();
myFunc = func;
}
//=============================================
// OSD_Thread::Run
//=============================================
#ifdef _WIN32
#include <malloc.h>
// On Windows the signature of the thread function differs from that on UNIX/Linux.
// As we use the same definition of the thread function on all platforms (POSIX-like),
// we need to introduce appropriate wrapper function on Windows.
struct WNTthread_data
{
void* data;
OSD_ThreadFunction func;
};
static DWORD WINAPI WNTthread_func(LPVOID data)
{
WNTthread_data* adata = (WNTthread_data*)data;
void* ret = adata->func(adata->data);
free(adata);
return PtrToLong(ret);
}
#endif
bool OSD_Thread::Run(void* const data,
#ifdef _WIN32
const int WNTStackSize
#else
const int
#endif
)
{
if (!myFunc)
{
return false;
}
// detach current thread, if open
Detach();
#ifdef _WIN32
// allocate intermediate data structure to pass both data parameter and address
// of the real thread function to Windows thread wrapper function
WNTthread_data* adata = (WNTthread_data*)malloc(sizeof(WNTthread_data));
if (!adata)
return false;
adata->data = data;
adata->func = myFunc;
// then try to create a new thread
DWORD aThreadId = DWORD();
myThread = CreateThread(NULL, WNTStackSize, WNTthread_func, adata, 0, &aThreadId);
myThreadId = aThreadId;
if (myThread)
SetThreadPriority(myThread, myPriority);
else
{
memset(adata, 0, sizeof(WNTthread_data));
free(adata);
}
#else
if (pthread_create(&myThread, nullptr, myFunc, data) != 0)
{
myThread = OSD_PTHREAD_NULL;
}
else
{
myThreadId = (Standard_ThreadId)myThread;
}
#endif
return myThread != OSD_PTHREAD_NULL;
}
//=============================================
// OSD_Thread::Detach
//=============================================
void OSD_Thread::Detach()
{
#ifdef _WIN32
// On Windows, close current handle
if (myThread)
CloseHandle(myThread);
#else
// On Unix/Linux, detach a thread
if (myThread)
{
pthread_detach(myThread);
}
#endif
myThread = OSD_PTHREAD_NULL;
myThreadId = 0;
}
//=============================================
// OSD_Thread::Wait
//=============================================
bool OSD_Thread::Wait(void*& theResult)
{
// check that thread handle is not null
theResult = nullptr;
if (!myThread)
{
return false;
}
#ifdef _WIN32
// On Windows, wait for the thread handle to be signaled
if (WaitForSingleObject(myThread, INFINITE) != WAIT_OBJECT_0)
{
return false;
}
// and convert result of the thread execution to void*
DWORD anExitCode;
if (GetExitCodeThread(myThread, &anExitCode))
{
theResult = ULongToPtr(anExitCode);
}
CloseHandle(myThread);
myThread = OSD_PTHREAD_NULL;
myThreadId = 0;
return true;
#else
// On Unix/Linux, join the thread
if (pthread_join(myThread, &theResult) != 0)
{
return false;
}
myThread = OSD_PTHREAD_NULL;
myThreadId = 0;
return true;
#endif
}
//=============================================
// OSD_Thread::Wait
//=============================================
bool OSD_Thread::Wait(const int theTimeMs, void*& theResult)
{
// check that thread handle is not null
theResult = nullptr;
if (!myThread)
{
return false;
}
#ifdef _WIN32
// On Windows, wait for the thread handle to be signaled
DWORD ret = WaitForSingleObject(myThread, theTimeMs);
if (ret == WAIT_OBJECT_0)
{
DWORD anExitCode;
if (GetExitCodeThread(myThread, &anExitCode))
{
theResult = ULongToPtr(anExitCode);
}
CloseHandle(myThread);
myThread = OSD_PTHREAD_NULL;
myThreadId = 0;
return true;
}
else if (ret == WAIT_TIMEOUT)
{
return false;
}
return false;
#else
#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
#if __GLIBC_PREREQ(2, 4)
#define HAS_TIMED_NP
#endif
#endif
#ifdef HAS_TIMED_NP
struct timespec aTimeout;
if (clock_gettime(CLOCK_REALTIME, &aTimeout) == -1)
{
return false;
}
time_t aSeconds = (theTimeMs / 1000);
long aNanoseconds = (theTimeMs - aSeconds * 1000) * 1000000L;
aTimeout.tv_sec += aSeconds;
aTimeout.tv_nsec += aNanoseconds;
// Normalize nanoseconds overflow to seconds
if (aTimeout.tv_nsec >= 1000000000L)
{
aTimeout.tv_sec += aTimeout.tv_nsec / 1000000000L;
aTimeout.tv_nsec = aTimeout.tv_nsec % 1000000000L;
}
if (pthread_timedjoin_np(myThread, &theResult, &aTimeout) != 0)
{
return false;
}
#else
// join the thread without timeout
(void)theTimeMs;
if (pthread_join(myThread, &theResult) != 0)
{
return false;
}
#endif
myThread = OSD_PTHREAD_NULL;
myThreadId = 0;
return true;
#endif
}
//=============================================
// OSD_Thread::GetId
//=============================================
Standard_ThreadId OSD_Thread::GetId() const
{
return myThreadId;
}
//=============================================
// OSD_Thread::Current
//=============================================
Standard_ThreadId OSD_Thread::Current()
{
#ifdef _WIN32
return GetCurrentThreadId();
#else
return (Standard_ThreadId)pthread_self();
#endif
}
4f95ecaa3This file is pinned to the selected release. Download the original to open it in your design tool.