One common problem when programming with threads is coordinating startup and shutdown of threads. Often, the creators of threads do not wish to proceed until they are sure that the created thread has been scheduled at least once, and thus had a chance to perform any necessary local initialization before dispatching its workload. Likewise, when shutting down a system, allocators of resources often wish to be sure that worker threads are no longer using resources before deallocating them. To simplify these activities, NASD provides an abstraction called a thread group. This is a structure used to control and coordinate startup and shutdown of one or more threads.
Thread groups have type nasd_threadgroup_t
. They are
intialized with nasd_init_threadgroup()
and cleaned
up with nasd_destroy_threadgroup()
, both of which return
nasd_status_t
.
All thread group operations take as their sole argument a pointer
to a nasd_threadgroup_t
. To utilize a thread group,
it must first be initialized (nasd_init_threadgroup()
).
When a thread is created, the creator of the thread should call
NASD_THREADGROUP_STARTED()
on the associated group.
When it is ready to perform its work, that thread should call
NASD_THREADGROUP_RUNNING()
. When it is no longer
dispatching its workload, and will never again touch any resources
which it might be expected to use during the course of its usual
work, that thread should call NASD_THREADGROUP_DONE()
.
Normally, this takes place immediately before the thread in question
ceases execution (NASD_THREAD_KILL_SELF()
). The creator
of the thread calls NASD_THREADGROUP_WAIT_START()
to wait for all threads to be ready to dispatch their workload.
To wait for all threads in a group to be done dispatching their
workload (that is, to wait for them all to call
NASD_THREADGROUP_DONE()
), NASD_THREADGROUP_WAIT_STOP()
should be called.
It is also useful to have a consistent way for threads to indicate
to one another that they should stop dispatching their workload and exit,
or for worker threads to check if they should do so. To instruct threads
in a group to cease dispatching their workload, a thread should call
NASD_THREADGROUP_INDICATE_SHUTDOWN()
on the group. When
NASD_THREADGROUP_SHUTDOWNP()
evaluates nonzero on a group,
someone has called NASD_THREADGROUP_INDICATE_SHUTDOWN()
on
the group (it evaluates zero if no one has done so). This mechanism relies
on the threads involved explicitly informing one another that this
condition has changed. For instance, a worker thread which alternates
blocking to await an event to dispatch and dispatching the event should
check NASD_THREADGROUP_SHUTDOWNP()
before and after blocking.
The following fragments of code illustrate how one uses a thread group to coordinate starting and stopping a group of threads, and how threads in that group coordinate. Although this example creates multiple worker threads, it is perfectly appropriate to use a thread group to manage the starting and stopping of a single thread.
![]() | ![]() | ![]() |
---|---|---|
Threads | Memory | NASD Programmer's Documentation |