Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/common/Task.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ WorkerThread* WorkerThread::start(Coordinator* coordinator)
{
AutoPtr<WorkerThread> thd = FB_NEW WorkerThread(coordinator);

Thread::start(workerThreadRoutine, thd, THREAD_medium, &thd->m_thdHandle);
Thread::start(workerThreadRoutine, thd, THREAD_medium, &thd->m_thread);

return thd.release();
}
Expand Down Expand Up @@ -122,7 +122,7 @@ void WorkerThread::shutdown(bool wait)

if (wait)
{
Thread::waitForCompletion(m_thdHandle);
m_thread.waitForCompletion();
m_state = SHUTDOWN;
}
}
Expand Down
7 changes: 1 addition & 6 deletions src/common/Task.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,6 @@ class WorkerThread final
~WorkerThread()
{
shutdown(true);

#ifdef WIN_NT
if (m_thdHandle != INVALID_HANDLE_VALUE)
CloseHandle(m_thdHandle);
#endif
}

static WorkerThread* start(Coordinator*);
Expand All @@ -196,7 +191,7 @@ class WorkerThread final
Semaphore m_waitSem; // idle thread waits on this semaphore to start work or go out
Semaphore m_signalSem; // semaphore is released when thread going idle
STATE m_state;
Thread::Handle m_thdHandle;
Thread m_thread;
};

} // namespace Jrd
Expand Down
150 changes: 59 additions & 91 deletions src/common/ThreadStart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ THREAD_ENTRY_DECLARE threadStart(THREAD_ENTRY_PARAM arg)

#ifdef USE_POSIX_THREADS
#define START_THREAD
Thread Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle)
void Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Thread* pThread)
{
/**************************************
*
Expand All @@ -117,17 +117,18 @@ Thread Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Han
* status if not.
*
**************************************/
pthread_t thread;
pthread_t* p_thread = p_handle ? p_handle : &thread;
Thread thread;
if (!pThread)
pThread = &thread;
int state;

#if defined (LINUX) || defined (FREEBSD)
if ((state = pthread_create(p_thread, NULL, THREAD_ENTRYPOINT, THREAD_ARG)))
if ((state = pthread_create(&pThread->m_handle, NULL, THREAD_ENTRYPOINT, THREAD_ARG)))
Firebird::system_call_failed::raise("pthread_create", state);

if (!p_handle)
if (pThread == &thread)
{
if ((state = pthread_detach(*p_thread)))
if ((state = pthread_detach(pThread->m_handle)))
Firebird::system_call_failed::raise("pthread_detach", state);
}
#else
Expand Down Expand Up @@ -162,13 +163,13 @@ Thread Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Han
if (state)
Firebird::system_call_failed::raise("pthread_attr_setscope", state);

if (!p_handle)
if (pThread == &thread)
{
state = pthread_attr_setdetachstate(&pattr, PTHREAD_CREATE_DETACHED);
if (state)
Firebird::system_call_failed::raise("pthread_attr_setdetachstate", state);
}
state = pthread_create(p_thread, &pattr, THREAD_ENTRYPOINT, THREAD_ARG);
state = pthread_create(&pThread->m_handle, &pattr, THREAD_ENTRYPOINT, THREAD_ARG);
int state2 = pthread_attr_destroy(&pattr);
if (state)
Firebird::system_call_failed::raise("pthread_create", state);
Expand All @@ -177,37 +178,45 @@ Thread Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Han

#endif

if (p_handle)
{
#ifdef HAVE_PTHREAD_CANCEL
if (pThread != &thread)
{
int dummy; // We do not want to know old cancel type
state = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &dummy);
if (state)
Firebird::system_call_failed::raise("pthread_setcanceltype", state);
#endif
}

return Thread(*p_thread);
#endif
}

void Thread::waitForCompletion(Handle& thread)
void Thread::waitForCompletion()
{
int state = pthread_join(thread, NULL);
if (state)
Firebird::system_call_failed::raise("pthread_join", state);
if (isValid())
{
int state = pthread_join(m_handle, NULL);
if (state)
Firebird::system_call_failed::raise("pthread_join", state);
m_handle = INVALID_HANDLE;
}
}

void Thread::kill(Handle& thread)
// ignore errors - this is abnormal completion call
void Thread::kill() noexcept
{
#ifdef HAVE_PTHREAD_CANCEL
int state = pthread_cancel(thread);
if (state)
Firebird::system_call_failed::raise("pthread_cancel", state);
waitForCompletion(thread);
if (isValid())
{
pthread_cancel(m_handle);
try
{
waitForCompletion();
}
catch(...) { }
}
#endif
}

ThreadId Thread::getId()
ThreadId Thread::getCurrentThreadId()
{
#ifdef USE_LWP_AS_THREAD_ID
static __thread int tid = 0;
Expand All @@ -219,15 +228,9 @@ ThreadId Thread::getId()
#endif
}

bool Thread::isCurrent(Handle threadHandle)
bool Thread::isCurrent() const noexcept
{
static_assert(std::is_same<Handle, InternalId>().value, "type mismatch");
return pthread_equal(threadHandle, pthread_self());
}

bool Thread::isCurrent()
{
return pthread_equal(internalId, pthread_self());
return isValid() && pthread_equal(m_handle, pthread_self());
}

void Thread::sleep(unsigned milliseconds)
Expand Down Expand Up @@ -274,7 +277,7 @@ void Thread::yield()

#ifdef WIN_NT
#define START_THREAD
Thread Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle)
void Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Thread* pThread)
{
/**************************************
*
Expand Down Expand Up @@ -331,52 +334,57 @@ Thread Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Han

SetThreadPriority(handle, priority);

if (p_handle)
if (pThread)
{
*p_handle = handle;
*pThread = Thread(handle, thread_id);
ResumeThread(handle);
}
else
{
ResumeThread(handle);
CloseHandle(handle);
}
}

return Thread(thread_id);
bool Thread::waitFor(unsigned milliseconds) const noexcept
{
if (!isValid())
return true;

return WaitForSingleObject(m_handle, milliseconds) != WAIT_TIMEOUT;
}

void Thread::waitForCompletion(Handle& handle)
void Thread::waitForCompletion()
{
if (!isValid())
return;

// When current DLL is unloading, OS loader holds loader lock. When thread is
// exiting, OS notifies every DLL about it, and acquires loader lock. In such
// scenario waiting on thread handle will never succeed.
if (!Firebird::dDllUnloadTID) {
WaitForSingleObject(handle, 10000);
WaitForSingleObject(m_handle, 10000); // error handler ????????????
}
CloseHandle(handle);
handle = 0;
detach();
}

void Thread::kill(Handle& handle)
void Thread::kill() noexcept
{
TerminateThread(handle, -1);
CloseHandle(handle);
handle = 0;
if (isValid())
{
TerminateThread(m_handle, -1);
detach();
}
}

ThreadId Thread::getId()
ThreadId Thread::getCurrentThreadId()
{
return GetCurrentThreadId();
}

bool Thread::isCurrent(Handle threadHandle)
{
return GetCurrentThreadId() == GetThreadId(threadHandle);
}

bool Thread::isCurrent()
bool Thread::isCurrent() const noexcept
{
return GetCurrentThreadId() == internalId;
return isValid() && (GetCurrentThreadId() == m_Id);
}

void Thread::sleep(unsigned milliseconds)
Expand All @@ -390,43 +398,3 @@ void Thread::yield()
}

#endif // WIN_NT


#ifndef START_THREAD
ThreadId Thread::start(ThreadEntryPoint* routine, void* arg, int priority_arg, Handle* p_handle)
{
/**************************************
*
* t h r e a d _ s t a r t ( G e n e r i c )
*
**************************************
*
* Functional description
* Wrong attempt to start a new thread.
*
**************************************/
fb_assert(false);
return 0;
}

void Thread::waitForCompletion(Handle&)
{
}

void Thread::kill(Handle&)
{
}

Thread::Handle Thread::getId()
{
}

void Thread::sleep(unsigned milliseconds)
{
}

void Thread::yield()
{
}

#endif // START_THREAD
Loading
Loading