My application creates a thread and that runs in the background all the time. I can only terminate the thread manually, not from within the thread callback function.
At the moment I am using TerminateThread() to kill that thread but it's causing it to hang sometimes.
I know there is a way to use events and WaitForSingleObject() to make the thread terminate gracefully but I can't find an example about that.
Please, code is needed here.
TerminateThread is a bad idea, especially if your thread uses synchronization objects such as mutexes. It can lead to unreleased memory and handles, and to deadlocks, so you're correct that you need to do something else.
Typically, the way that a thread terminates is to return from the function that defines the thread. The main thread signals the worker thread to exit using an event object or a even a simple boolean if it's checked often enough. If the worker thread waits with WaitForSingleObject, you may need to change it to a WaitForMultipleObjects, where one of the objects is an event. The main thread would call SetEvent and the worker thread would wake up and return.
We really can't provide any useful code unless you show us what you're doing. Depending on what the worker thread is doing and how your main thread is communicating information to it, it could look very different.
Also, under [now very old] MSVC, you need to use _beginthreadex instead of CreateThread in order to avoid memory leaks in the CRT. See MSKB #104641.
Update:
One use of worker thread is as a "timer", to do some operation on regular intervals. At the most trivial:
for (;;) {
switch (WaitForSingleObject(kill_event, timeout)) {
case WAIT_TIMEOUT: /*do timer action*/ break;
default: return 0; /* exit the thread */
}
}
Another use is to do something on-demand. Basically the same, but with the timeout set to INFINITE and doing some action on WAIT_OBJECT_0 instead of WAIT_TIMEOUT. In this case you would need two events, one to make the thread wake up and do some action, another to make it wake up and quit:
HANDLE handles[2] = { action_handle, quit_handle };
for (;;) {
switch (WaitForMultipleObject(handles, 2, FALSE, INFINITE)) {
case WAIT_OBJECT_0 + 0: /* do action */ break;
default:
case WAIT_OBJECT_0 + 1: /* quit */ break;
}
}
Note that it's important that the loop do something reasonable if WFSO/WFMO return an error instead of one of the expected results. In both examples above, we simply treat an error as if we had been signaled to quit.
You could achieve the same result with the first example by closing the event handle from the main thread, causing the worker thread get an error from WaitForSingleObject and quit, but I wouldn't recommend that approach.
Since you don't know what the thread is doing, there is no way to safely terminate the thread from outside.
Why do you think you cannot terminate it from within?
You can create an event prior to starting the thread and pass that event's handle to the thread. You call SetEvent() on that event from the main thread to signal the thread to stop and then WaitForSingleObject on the thread handle to wait for the thread to actually have finished. Within the threads loop, you call WaitForSingleObject() on the event, specifying a timeout of 0 (zero), so that the call returns immediately even if the event is not set. If that call returns WAIT_TIMEOUT, the event is not set, if it returns WAIT_OBJECT_0, it is set. In the latter case you return from the thread function.
I presume your thread isn't just burning CPU cycles in an endless loop, but does some waiting, maybe through calling Sleep(). If so, you can do the sleeping in WaitForSingleObject instead, by passing a timeout to it.
What are you doing in the background thread? If you're looping over something, you can end the thread within itself by having a shared public static object (like a Boolean) that you set to true from the foreground thread and that the background thread checks for and exits cleanly when set to true.
It is a code example for thread management in the fork-join manner. It use struct Thread as a thread descriptor.
Let's introduce some abstraction of the thread descriptor data structure:
#include <Windows.h>
struct Thread
{
volatile BOOL stop;
HANDLE event;
HANDLE thread;
};
typedef DWORD ( __stdcall *START_ROUTINE)(struct Thread* self, LPVOID lpThreadParameter);
struct BootstrapArg
{
LPVOID arg;
START_ROUTINE body;
struct Thread* self;
};
Functions for the thread parent use:
StartThread() initialize this structure and launches new thread.
StopThread() initiate thread termination and wait until thread will be actually terminated.
DWORD __stdcall ThreadBootstrap(LPVOID lpThreadParameter)
{
struct BootstrapArg ba = *(struct BootstrapArg*)lpThreadParameter;
free(lpThreadParameter);
return ba.body(ba.self, ba.arg);
}
VOID StartThread(struct Thread* CONST thread, START_ROUTINE body, LPVOID arg)
{
thread->event = CreateEvent(NULL, TRUE, FALSE, NULL);
thread->stop = FALSE;
thread->thread = NULL;
if ((thread->event != NULL) && (thread->event != INVALID_HANDLE_VALUE))
{
struct BootstrapArg* ba = (struct BootstrapArg*)malloc(sizeof(struct BootstrapArg));
ba->arg = arg;
ba->body = body;
ba->self = thread;
thread->thread = CreateThread(NULL, 0, ThreadBootstrap, ba, 0, NULL);
if ((thread->thread == NULL) || (thread->thread == INVALID_HANDLE_VALUE))
{
free(ba);
}
}
}
DWORD StopThread(struct Thread* CONST thread)
{
DWORD status = ERROR_INVALID_PARAMETER;
thread->stop = TRUE;
SetEvent(thread->event);
WaitForSingleObject(thread->thread, INFINITE);
GetExitCodeThread(thread->thread, &status);
CloseHandle(thread->event);
CloseHandle(thread->thread);
thread->event = NULL;
thread->thread = NULL;
return status;
}
This set of functions is expected to be used from the thread launched by StartThread():
IsThreadStopped() - Check for the termination request. Must be used after waiting on the below functions to identify the actual reason of the termination of waiting state.
ThreadSleep() - Replaces use of Sleep() for intra-thread code.
ThreadWaitForSingleObject() - Replaces use of WaitForSingleObject() for intra-thread code.
ThreadWaitForMultipleObjects() - Replaces use of WaitForMultipleObjects() for intra-thread code.
First function can be used for light-weight checks for termination request during long-running job processing. (For example big file compression).
Rest of the functions handle the case of waiting for some system resources, like events, semaphores etc. (For example worker thread waiting new request arriving from the requests queue).
BOOL IsThreadStopped(struct Thread* CONST thread)
{
return thread->stop;
}
VOID ThreadSleep(struct Thread* CONST thread, DWORD dwMilliseconds)
{
WaitForSingleObject(thread->event, dwMilliseconds);
}
DWORD ThreadWaitForSingleObject(struct Thread* CONST thread, HANDLE hHandle, DWORD dwMilliseconds)
{
HANDLE handles[2] = {hHandle, thread->event};
return WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds);
}
DWORD ThreadWaitForMultipleObjects(struct Thread* CONST thread, DWORD nCount, CONST HANDLE* lpHandles, DWORD dwMilliseconds)
{
HANDLE* handles = (HANDLE*)malloc(sizeof(HANDLE) * (nCount + 1U));
DWORD status;
memcpy(handles, lpHandles, nCount * sizeof(HANDLE));
handles[nCount] = thread->event;
status = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds);
free(handles);
return status;
}
Related
I have a timer that runs at regular intervals. I create the timer using timer_create() using the SIGEV_THREAD option. This will fire a callback on a thread when the timer expires, rather than send a SIGALRM signal to the process. The problem is, every time my timer expires, a new thread is spawned. This means the program spawns potentially hundreds of threads, depending on the frequency of the timer.
What would be better is to have one thread that handles the callbacks. I can do this when using timer_create() with signals (by using sigaction), but not threads only.
Is there any way to not use signals, but still have the timer notify the process in a single existing thread?
Or should I even worry about this from a performance perspective (threads vs signals)?
EDIT:
My solution was to use SIGEV_SIGNAL and pthread_sigmask(). So, I continue to rely on signals to know when my timer expires, but I can be 100% sure only a single thread (created by me) is being used to capture the signals and execute the appropriate action.
tl;dr: The basic premise that SIGEV_THREAD doesn't work based on signals is false - signals are the underlying mechanism through which new threads are spawned. glibc has no support for reutilizing the same thread for multiple callbacks.
timer_create doesn't behave exactly the way you think - its second parameter, struct sigevent *restrict sevp contains the field sigevent_notify which has following documentation:
SIGEV_THREAD
Notify the process by invoking sigev_notify_function "as
if" it were the start function of a new thread. (Among the
implementation possibilities here are that each timer notification
could result in the creation of a new thread, or that a single thread
is created to receive all notifications.) The function is invoked
with sigev_value as its sole argument. If sigev_notify_attributes is
not NULL, it should point to a pthread_attr_t structure that defines
attributes for the new thread (see pthread_attr_init(3)).
And indeed, if we look at glibc's implementation:
else
{
/* Create the helper thread. */
pthread_once (&__helper_once, __start_helper_thread);
...
struct sigevent sev =
{ .sigev_value.sival_ptr = newp,
.sigev_signo = SIGTIMER,
.sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID,
._sigev_un = { ._pad = { [0] = __helper_tid } } };
/* Create the timer. */
INTERNAL_SYSCALL_DECL (err);
int res;
res = INTERNAL_SYSCALL (timer_create, err, 3,
syscall_clockid, &sev, &newp->ktimerid);
And we can see __start_helper_thread's implementation:
void
attribute_hidden
__start_helper_thread (void)
{
...
int res = pthread_create (&th, &attr, timer_helper_thread, NULL);
And follow along to timer_helper_thread's implementation:
static void *
timer_helper_thread (void *arg)
{
...
/* Endless loop of waiting for signals. The loop is only ended when
the thread is canceled. */
while (1)
{
...
int result = SYSCALL_CANCEL (rt_sigtimedwait, &ss, &si, NULL, _NSIG / 8);
if (result > 0)
{
if (si.si_code == SI_TIMER)
{
struct timer *tk = (struct timer *) si.si_ptr;
...
(void) pthread_create (&th, &tk->attr,
timer_sigev_thread, td);
So - at least at the glibc level - when using SIGEV_THREAD you are necessarily using signals to signal a thread to create the function anyways - and it seems like your primary motivation to begin with was avoiding the use of alarm signals.
At the Linux source code level, timers seems to work on signals alone - the posix_timer_event in kernel/time/posix_timers.c function (called by alarm_handle_timer in kernel/time/alarmtimer.c) goes straight to code in signal.c that necessarily sends a signal. So it doesn't seem possible to avoid signals when working with timer_create, and this statement from your question - "This will fire a callback on a thread when the timer expires, rather than send a SIGALRM signal to the process." - is false (though it's true that the signal doesn't have to be SIGALRM).
In other words - there seem to be no performance benefits to be gained from SIGEV_THREAD as opposed to signals. Signals will still be used to trigger the creation of threads, and you're adding the additional overhead of creating new threads.
I've created a Timer pseudo class in C that has call back capability and can be cancelled. I come from the .NET/C# world where this is all done by the framework and I'm not an expert with pthreads.
In .NET there are cancellation tokens which you can wait on which means I don't need to worry so much about the nuts and bolts.
However using pthreads is a bit more low level than I am used to so my question is:
Are there any issues with the way I have implemented this?
Thanks in anticipation for any comments you may have.
Timer struct:
typedef struct _timer
{
pthread_cond_t Condition;
pthread_mutex_t ConditionMutex;
bool IsRunning;
pthread_mutex_t StateMutex;
pthread_t Thread;
int TimeoutMicroseconds;
void * Context;
void (*Callback)(bool isCancelled, void * context);
} TimerObject, *Timer;
C Module:
static void *
TimerTask(Timer timer)
{
struct timespec timespec;
struct timeval now;
int returnValue = 0;
clock_gettime(CLOCK_REALTIME, ×pec);
timespec.tv_sec += timer->TimeoutMicroseconds / 1000000;
timespec.tv_nsec += (timer->TimeoutMicroseconds % 1000000) * 1000000;
pthread_mutex_lock(&timer->StateMutex);
timer->IsRunning = true;
pthread_mutex_unlock(&timer->StateMutex);
pthread_mutex_lock(&timer->ConditionMutex);
returnValue = pthread_cond_timedwait(&timer->Condition, &timer->ConditionMutex, ×pec);
pthread_mutex_unlock(&timer->ConditionMutex);
if (timer->Callback != NULL)
{
(*timer->Callback)(returnValue != ETIMEDOUT, timer->Context);
}
pthread_mutex_lock(&timer->StateMutex);
timer->IsRunning = false;
pthread_mutex_unlock(&timer->StateMutex);
return 0;
}
void
Timer_Initialize(Timer timer, void (*callback)(bool isCancelled, void * context))
{
pthread_mutex_init(&timer->ConditionMutex, NULL);
timer->IsRunning = false;
timer->Callback = callback;
pthread_mutex_init(&timer->StateMutex, NULL);
pthread_cond_init(&timer->Condition, NULL);
}
bool
Timer_IsRunning(Timer timer)
{
pthread_mutex_lock(&timer->StateMutex);
bool isRunning = timer->IsRunning;
pthread_mutex_unlock(&timer->StateMutex);
return isRunning;
}
void
Timer_Start(Timer timer, int timeoutMicroseconds, void * context)
{
timer->Context = context;
timer->TimeoutMicroseconds = timeoutMicroseconds;
pthread_create(&timer->Thread, NULL, TimerTask, (void *)timer);
}
void
Timer_Stop(Timer timer)
{
void * returnValue;
pthread_mutex_lock(&timer->StateMutex);
if (!timer->IsRunning)
{
pthread_mutex_unlock(&timer->StateMutex);
return;
}
pthread_mutex_unlock(&timer->StateMutex);
pthread_cond_broadcast(&timer->Condition);
pthread_join(timer->Thread, &returnValue);
}
void
Timer_WaitFor(Timer timer)
{
void * returnValue;
pthread_join(timer->Thread, &returnValue);
}
Example use:
void
TimerExpiredCallback(bool cancelled, void * context)
{
fprintf(stderr, "TimerExpiredCallback %s with context %s\n",
cancelled ? "Cancelled" : "Timed Out",
(char *)context);
}
void
ThreadedTimerExpireTest()
{
TimerObject timerObject;
Timer_Initialize(&timerObject, TimerExpiredCallback);
Timer_Start(&timerObject, 5 * 1000000, "Threaded Timer Expire Test");
Timer_WaitFor(&timerObject);
}
void
ThreadedTimerCancelTest()
{
TimerObject timerObject;
Timer_Initialize(&timerObject, TimerExpiredCallback);
Timer_Start(&timerObject, 5 * 1000000, "Threaded Timer Cancel Test");
Timer_Stop(&timerObject);
}
Overall, it seems pretty solid work for someone who ordinarily works in different languages and who has little pthreads experience. The idea seems to revolve around pthread_cond_timedwait() to achieve a programmable delay with a convenient cancellation mechanism. That's not unreasonable, but there are, indeed, a few problems.
For one, your condition variable usage is non-idiomatic. The conventional and idiomatic use of a condition variable associates with each wait a condition for whether the thread is clear to proceed. This is tested, under protection of the mutex, before waiting. If the condition is satisfied then no wait is performed. It is tested again after each wakeup, because there is a variety of scenarios in which a thread may return from waiting even though it is not actually clear to proceed. In these cases, it loops back and waits again.
I see at least two such possibilities with your timer:
The timer is cancelled very quickly, before its thread starts to wait. Condition variables do not queue signals, so in this case the cancellation would be ineffective. This is a form of race condition.
Spurious wakeup. This is always a possibility that must be considered. Spurious wakeups are rare under most circumstances, but they really do happen.
It seems natural to me to address that by generalizing your IsRunning to cover more states, perhaps something more like
enum { NEW, RUNNING, STOPPING, FINISHED, ERROR } State;
, instead.
Of course, you still have to test that under protection of the appropriate mutex, which brings me to my next point: one mutex should suffice. That one can and should serve both to protect shared state and as the mutex associated with the CV wait. This, too, is idiomatic. It would lead to code in TimerTask() more like this:
// ...
pthread_mutex_lock(&timer->StateMutex);
// Responsibility for setting the state to RUNNING transferred to Timer_Start()
while (timer->State == RUNNING) {
returnValue = pthread_cond_timedwait(&timer->Condition, &timer->StateMutex, ×pec);
switch (returnValue) {
case 0:
if (timer->State == STOPPING) {
timer->State = FINISHED;
}
break;
case ETIMEDOUT:
timer->State = FINISHED;
break;
default:
timer->State = ERROR;
break;
}
}
pthread_mutex_unlock(&timer->StateMutex);
// ...
The accompanying Timer_Start() and Timer_Stop() would be something like this:
void Timer_Start(Timer timer, int timeoutMicroseconds, void * context) {
timer->Context = context;
timer->TimeoutMicroseconds = timeoutMicroseconds;
pthread_mutex_lock(&timer->StateMutex);
timer->state = RUNNING;
// start the thread before releasing the mutex so that no one can see state
// RUNNING before the thread is actually running
pthread_create(&timer->Thread, NULL, TimerTask, (void *)timer);
pthread_mutex_unlock(&timer->StateMutex);
}
void Timer_Stop(Timer timer) {
_Bool should_join = 0;
pthread_mutex_lock(&timer->StateMutex);
switch (timer->State) {
case NEW:
timer->state = FINISHED;
break;
case RUNNING:
timer->state = STOPPING;
should_join = 1;
break;
case STOPPING:
should_join = 1;
break;
// else no action
}
pthread_mutex_unlock(&timer->StateMutex);
// Harmless if the timer has already stopped:
pthread_cond_broadcast(&timer->Condition);
if (should_join) {
pthread_join(timer->Thread, NULL);
}
}
A few other, smaller adjustments would be needed elsewhere.
Additionally, although the example code above omits it for clarity, you really should ensure that you test the return values of all the functions that provide status information that way, unless you don't care whether they succeeded. That includes almost all standard library and Pthreads functions. What you should do in the event that that one fails is highly contextual, but pretending (or assuming) that it succeeded, instead, is rarely a good choice.
An alternative
Another approach to a cancellable delay would revolve around select() or pselect() with a timeout. To arrange for cancellation, you set up a pipe, and have select() to listen to the read end. Writing anything to the write end will then wake select().
This is in several ways easier to code, because you don't need any mutexes or condition variables. Also, data written to a pipe persists until it is read (or the pipe is closed), which smooths out some of the timing-related issues that the CV-based approach has to code around.
With select, however, you need to be prepared to deal with signals (at minimum by blocking them), and the timeout is a duration, not an absolute time.
pthread_mutex_lock(&timer->StateMutex);
timer->IsRunning = true;
pthread_mutex_unlock(&timer->StateMutex);
pthread_mutex_lock(&timer->ConditionMutex);
returnValue = pthread_cond_timedwait(&timer->Condition, &timer->ConditionMutex, ×pec);
pthread_mutex_unlock(&timer->ConditionMutex);
if (timer->Callback != NULL)
{
(*timer->Callback)(returnValue != ETIMEDOUT, timer->Context);
}
You have two bugs here.
A cancellation can slip in after IsRunning is set to true and before pthread_cond_timedwait gets called. In this case, you'll wait out the entire timer. This bug exists because ConditionMutex doesn't protect any shared state. To use a condition variable properly, the mutex associated with the condition variable must protect the shared state. You can't trade the right mutex for the wrong mutex and then call pthread_cond_timedwait because that creates a race condition. The entire point of a condition variable is to provide an atomic "unlock and wait" operation to prevent this race condition and your code goes to effort to break that logic.
You don't check the return value of pthread_cond_timedwait. If neither the timeout has expired nor cancellation has been requested, you call the callback anyway. Condition variables are stateless. It is your responsibility to track and check state, the condition variable will not do this for you. You need to call pthread_cond_timedwait in a loop until either the state is set to STOPPING or the timeout is reached. Note that the mutex associated with the condition variable, as in 1 above, must protect the shared state -- in this case state.
I think you have a fundamental misunderstanding about how condition variable work and what they're for. They are used when you a mutex that protects shared state and you want to wait for that shared state to change. The mutex associated with the condition variable must protect the shared state to avoid the classic race condition where the state changes after you released the lock but before you managed to start waiting.
UPDATE:
To provide some more useful information, let me briefly explain what a condition variable is for. Say you have some shared state protected by a mutex. And say some thread can't make forward progress until that shared state changes.
You have a problem. You have to hold the mutex that protects the shared state to see what the state is. When you see that it's in the wrong state, you need to wait. But you also need to release the mutex or no other thread can change the shared state.
But if you unlock the mutex and then wait (which is what your code does above!) you have a race condition. After you unlock the mutex but before you wait, another thread can acquire the mutex and change the shared state such that you no longer want to wait. So you need an atomic "unlock the mutex and wait" operation.
That is the purpose, and the only purpose, of condition variables. So you can atomically release the mutex that protects some shared state and wait for a sign with no change for the signal to be lost in-between when you released the mutex and when you waited.
Another important point -- condition variables are stateless. They have no idea what you are waiting for. You must never call pthread_cond_wait or pthread_cond_timedwait and make assumptions about the state. You must check it yourself. Your code releases the mutex after pthread_cond_timedwait returns. You only want to do that if the call times out.
If pthread_cond_timedwait doesn't timeout (or, in any case, when pthread_cond_wait returns), you don't know what happened until you check the state. That's why these functions re-acquire the mutex -- so you can check the state and decide what to do. This is why these functions are almost always called in a loop -- if the thing you're waiting for still hasn't happened (which you determine by checking the shared state that you are responsible for), you need to keep waiting.
The perfect way to run and terminate threads in Windows using C is mentioned in the answer below!
There are 2 problems I'm facing with the current implementation method :
I can't forcibly stop the thread. For some reason it still continues. For example I have a for loop, it runs a function of which this thread example is a part. When this function is called 4-5 times, I see multiple animations on the screen suggesting that the previous threads didn't stop even when I called TerminateThread function at the end of my function.
At times the thread doesn't run at all and no animation is displayed on the screen. Which is if my function code runs really fast or for some other reason, I feel like the thread is being killed before it initializes. Is there a way to wait until init of thread?
How do I fix these issues?
Correct way of terminating threads is to signal the thread and let it finish gracefully, i.e.:
(updated to use interlocked intrinsics instead of a volatile flag, as per #IInspectable's comment below)
HANDLE eventHnd;
HANDLE threadHnd;
LONG isStopRequested = 0; // 1 = "stop requested"
static DWORD WINAPI thread_func(LPVOID lpParam)
{
do
{
// wait until signalled from a different thread
WaitForSingleObject(eventHnd, INFINITE);
// end thread if stop requested
if (InterlockedCompareExchange(&isStopRequested, 0, 0) == 1)
return 0;
// otherwise do some background work
Sleep(500);
} while (true);
}
The eventHnd variable is initialized using the CreateEvent function, and the stopRequested variable is just a boolean flag you can set from your main program:
// this creates an auto-reset event, initially set to 'false'
eventHnd = CreateEvent(NULL, false, false, NULL);
InterlockedExchange(&isStopRequested, 0);
threadHnd = CreateThread(NULL, 0, Processing_Thread, NULL, 0, NULL);
So, whenever you want to tell the thread do perform a task, you will simply set the event:
SetEvent(eventHnd);
And when you want to end the thread, you will set the flag to true, signal the event, and then wait for the thread to finish:
// request stop
InterlockedExchange(&isStopRequested, 1);
// signal the thread if it's waiting
SetEvent(eventHnd);
// wait until the thread terminates
WaitForSingleObject(threadHnd, 5000);
I am trying to figure out how to get rid of a reliance on the pthread_timedjoin_np because I am trying to build some code on OSX.
Right now I have a Queue of threads that I am popping from, doing that pthread_timedjoin_np and if they dont return, they get pushed back on the queue.
The end of the thread_function that is called for each thread does a pthread_exit(0); so that the recieving thread can check for a return value of zero.
I thought i might try to use pthread_cond_timedwait() to achieve a similar effect, however I think i am missing a step.
I thought I would be able to make worker Thread A signal a condition AND pthread_exit() within a mutex, , and worker Thread B could wake up on the signal, and then pthread_join(). The problem is, Thread B doesn't know which thread threw the conditional signal. Do I need to explicitly pass that as part of the conditonal signal or what?
Thanks
Derek
Here is a portable implementation of pthread_timedjoin_np. It's a bit costly, but it's a full drop-in replacement:
struct args {
int joined;
pthread_t td;
pthread_mutex_t mtx;
pthread_cond_t cond;
void **res;
};
static void *waiter(void *ap)
{
struct args *args = ap;
pthread_join(args->td, args->res);
pthread_mutex_lock(&args->mtx);
args->joined = 1;
pthread_mutex_unlock(&args->mtx);
pthread_cond_signal(&args->cond);
return 0;
}
int pthread_timedjoin_np(pthread_t td, void **res, struct timespec *ts)
{
pthread_t tmp;
int ret;
struct args args = { .td = td, .res = res };
pthread_mutex_init(&args.mtx, 0);
pthread_cond_init(&args.cond, 0);
pthread_mutex_lock(&args.mtx);
ret = pthread_create(&tmp, 0, waiter, &args);
if (!ret)
do ret = pthread_cond_timedwait(&args.cond, &args.mtx, ts);
while (!args.joined && ret != ETIMEDOUT);
pthread_mutex_unlock(&args.mtx);
pthread_cancel(tmp);
pthread_join(tmp, 0);
pthread_cond_destroy(&args.cond);
pthread_mutex_destroy(&args.mtx);
return args.joined ? 0 : ret;
}
There may be small errors since I wrote this on the spot and did not test it, but the concept is sound.
Producer-consumer queue. Have the threads queue *themselves, and so their results,(if any), to the queue before they exit. Wait on the queue.
No polling, no latency.
With your current design, you would have to join() the returned threads get the valueptr and to ensure that they are destroyed.
Maybe you could sometime move to a real threadpool, where task items are queued to threads that never terminate, (so eliminating thread create/terminate/destroy overhead)?
solution with alarm.
pthread should enable cancel, so it can stop by external.(even with pthread_timedjoin_np).
pthread_timedjoin_np return with ETIMEOUT after waited time.
set alarm, use alarm also can give "TIMEOUT" signal.
In handler, just pthread_cancel it. (only timeout run this).
pthread_join it in main thread.
reset alarm
I write test code in here:github
I am migrating an applciation from windows to linux. I am facing problem with respect to WaitForSingleObject and WaitForMultipleObjects interfaces.
In my application I spawn multiple threads where all threads wait for events from parent process or periodically run for every t seconds.
I have checked pthread_cond_timedwait, but we have to specify absolute time for this.
How can I implement this in Unix?
Stick to pthread_cond_timedwait and use clock_gettime. For example:
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += 10; // ten seconds
while (!some_condition && ret == 0)
ret = pthread_cond_timedwait(&cond, &mutex, &ts);
Wrap it in a function if you wish.
UPDATE: complementing the answer based on our comments.
POSIX doesn't have a single API to wait for "all types" of events/objects as Windows does. Each one has its own functions. The simplest way to notify a thread for termination is using atomic variables/operations. For example:
Main thread:
// Declare it globally (argh!) or pass by argument when the thread is created
atomic_t must_terminate = ATOMIC_INIT(0);
// "Signal" termination by changing the initial value
atomic_inc(&must_terminate);
Secondary thread:
// While it holds the default value
while (atomic_read(&must_terminate) == 0) {
// Keep it running...
}
// Do proper cleanup, if needed
// Call pthread_exit() providing the exit status
Another alternative is to send a cancellation request using pthread_cancel. The thread being cancelled must have called pthread_cleanup_push to register any necessary cleanup handler. These handlers are invoked in the reverse order they were registered. Never call pthread_exit from a cleanup handler, because it's undefined behaviour. The exit status of a cancelled thread is PTHREAD_CANCELED. If you opt for this alternative, I recommend you to read mainly about cancellation points and types.
And last but not least, calling pthread_join will make the current thread block until the thread passed by argument terminates. As bonus, you'll get the thread's exit status.
For what it's worth, we (NeoSmart Technologies) have just released an open source (MIT licensed) library called pevents which implements WIN32 manual and auto-reset events on POSIX, and includes both WaitForSingleObject and WaitForMultipleObjects clones.
Although I'd personally advise you to use POSIX multithreading and signaling paradigms when coding on POSIX machines, pevents gives you another choice if you need it.
I realise this is an old question now, but for anyone else who stumbles across it, this source suggests that pthread_join() does effectively the same thing as WaitForSingleObject():
http://www.ibm.com/developerworks/linux/library/l-ipc2lin1/index.html
Good luck!
For WaitForMultipleObjects with false WaitAll try this:
#include <unistd.h>
#include <pthread.h>
#include <stdio.h>
using namespace std;
pthread_cond_t condition;
pthread_mutex_t signalMutex;
pthread_mutex_t eventMutex;
int finishedTask = -1;
void* task(void *data)
{
int num = *(int*)data;
// Do some
sleep(9-num);
// Task finished
pthread_mutex_lock(&eventMutex); // lock until the event will be processed by main thread
pthread_mutex_lock(&signalMutex); // lock condition mutex
finishedTask = num; // memorize task number
pthread_cond_signal(&condition);
pthread_mutex_unlock(&signalMutex); // unlock condtion mutex
}
int main(int argc, char *argv[])
{
pthread_t thread[10];
pthread_cond_init(&condition, NULL);
pthread_mutex_init(&signalMutex, NULL); // First mutex locks signal
pthread_mutex_init(&eventMutex, NULL); // Second mutex locks event processing
int numbers[10];
for (int i = 0; i < 10; i++) {
numbers[i] = i;
printf("created %d\n", i); // Creating 10 asynchronous tasks
pthread_create(&thread[i], NULL, task, &numbers[i]);
}
for (int i = 0; i < 10;)
{
if (finishedTask >= 0) {
printf("Task %d finished\n", finishedTask); // handle event
finishedTask = -1; // reset event variable
i++;
pthread_mutex_unlock(&eventMutex); // unlock event mutex after handling
} else {
pthread_cond_wait(&condition, &signalMutex); // waiting for event
}
}
return 0;
}