Fixed binary search: no more infinite loops when vendor is unknown.
[tangerine.git] / workbench / libs / thread / waitthread.c
blob35cd8c7774ea18a61123c175db300323b8dfee1d
1 /*
2 * thread.library - threading and synchronisation primitives
4 * Copyright © 2007 Robert Norris
6 * This program is free software; you can redistribute it and/or modify it
7 * under the same terms as AROS itself.
8 */
10 #include "thread_intern.h"
12 #include <exec/types.h>
13 #include <exec/tasks.h>
14 #include <proto/exec.h>
15 #include <proto/thread.h>
16 #include <assert.h>
18 /*****************************************************************************
20 NAME */
21 AROS_LH2(BOOL, WaitThread,
23 /* SYNOPSIS */
24 AROS_LHA(uint32_t, thread_id, D0),
25 AROS_LHA(void **, result, A1),
27 /* LOCATION */
28 struct ThreadBase *, ThreadBase, 6, Thread)
30 /* FUNCTION
31 Blocks the current task until the requested thread exits.
33 INPUTS
34 thread_id - ID of thread to detach.
35 result - pointer to storage for the thread's return value. You can
36 pass NULL here if you don't care about the return value.
38 RESULT
39 TRUE when the thread completed successfully. FALSE if thread could not
40 be waited on.
42 NOTES
43 A thread cannot wait on itself. A thread cannot be waited on if it is
44 detached.
46 If the thread has already completed, this call returns immediately with
47 the thread result. Further calls to this function for that thread will
48 fail.
50 Multiple threads can wait for a thread to complete. They will all
51 be notified when the thread completes, and will all receive the result.
53 EXAMPLE
54 void *ret;
55 WaitThread(id, &ret);
57 BUGS
59 SEE ALSO
60 CreateThread(), CurrentThread(), DetachThread()
62 INTERNALS
64 *****************************************************************************/
66 AROS_LIBFUNC_INIT
68 struct _Thread *thread;
70 assert(thread_id);
72 /* get the thread */
73 if ((thread = _getthreadbyid(thread_id, ThreadBase)) == NULL)
74 return FALSE;
76 ObtainSemaphore(&thread->lock);
78 /* can't wait for ourselves, that would be silly */
79 if (thread->task == FindTask(NULL)) {
80 ReleaseSemaphore(&thread->lock);
81 return FALSE;
84 /* can't wait on detached threads */
85 if (thread->detached) {
86 ReleaseSemaphore(&thread->lock);
87 return FALSE;
90 /* we only want to wait if the thread is still running */
91 if (thread->task != NULL) {
93 /* one more waiter */
94 thread->exit_count++;
95 ReleaseSemaphore(&thread->lock);
97 /* wait for exit */
98 LockMutex(thread->exit_mutex);
99 WaitCondition(thread->exit, thread->exit_mutex);
100 UnlockMutex(thread->exit_mutex);
102 ObtainSemaphore(&thread->lock);
104 /* no longer waiting */
105 thread->exit_count--;
108 /* copy the result if the caller was interested */
109 if (result != NULL)
110 *result = thread->result;
112 /* still more threads waiting, so we're done */
113 if (thread->exit_count > 0) {
114 ReleaseSemaphore(&thread->lock);
115 return TRUE;
118 /* nobody else cares about this thread */
120 /* remove it from the thread list */
121 ObtainSemaphore(&ThreadBase->lock);
122 REMOVE(thread);
123 ReleaseSemaphore(&ThreadBase->lock);
125 /* and clean it up */
126 DestroyCondition(thread->exit);
127 DestroyMutex(thread->exit_mutex);
128 FreeVec(thread);
130 return TRUE;
132 AROS_LIBFUNC_EXIT
133 } /* WaitThread */