PThreads: An Introduction for Windows Programmers

Historical Note

The first versions of UNIX had no concept of threads. Processes could be forked as shown in the example below:

pid_t child_pid = fork();
if (child_pid > 0) {
   printf("This is the parent process.\n");
   wait(child_pid);
} else {
   printf("This is the child process.\n");
}

Both the parent and the forked child process continue from the point fork is called. The return value from fork is different. The two processes share the same memory on a copy-on-write basis. Later this concept was extended to threads. A thread is essentially a forked process except the memory is shared for read and write. The child process starts at the function address passed to pthread_create

Thread Creation and Destruction

  • pthread_create creates a thread and returns a thread handle of type pthread_t
  • pthread-exit exits a thread with a result value, although return from the original thread function would be a better way of doing so
  • pthread_join waits for the child thread to complete and returns the return value from the child thread… unless the child thread is detached in which case it will return an error.

Detaching a thread
A thread can detached after its creation by calling pthread_detach or while creating the thread as shown below:

pthread_attr_t attr;
pthread_t thread;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread, &attr, &thread_function, NULL);
pthread_attr_destroy (&attr);

—————————————-

Thread Local Storage

  • pthread_keycreate creates a key, of type pthread_key_t whose use is explained below
  • pthread_setspecific associates a pointer with a (current_thread,key) pair
  • pthread_getspecific gets the value associated with the (current_thread,key) pair

Mutex

  • pthread_mutex_init initialises a mutex variable of type pthread_mutex_t
  • pthread_mutex_lock enters critical section
  • pthread_mutex_unlock exit critical section
  • pthread_mutex_trylock waits for critical section for a finite time
  • pthread_mutex_destroy destroys critical section

By default a mutex is non recursive. By comparison a CRITICAL_SECTION in Windows is always recursive. A mutex can be initialised to recursive like this

pthread_mutex_t Mutex;
pthread_mutexattr_t Attr;
pthread_mutexattr_init(&Attr);
pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&Mutex, &Attr)

———————————————————————–

Semaphore

  • sem_init initialise a variable of type sem_t
  • sem_post signals a semaphore
  • sem_wait waits for a semaphore
  • sem_getvalue gets the current value. Equivalent functionality is not available in Windows.
  • sem_destroy destroys semaphore, releases associated resources

Condition Variable

  • pthread_cond_init initialise a variable of type pthread_cond_t
  • pthread_cond_wait releases the mutex and waits for condition variable and wakes up if mutex can be acquired again.
  • pthread_cond_signal signals condition variable only one thread can wake up
  • pthread_cond_broadcast broadcasts the signal and multiple threads can wake up if they are not using the same mutex
  • pthread_cond_destroy destroys condition variable

Cancelling a thread
Thread cancellation is a rather esoteric feature that I have rarely come across in well written code. A thread can be in one of three cancellation states

  • asynchronously cancelable
  • synchronously cancelable
  • uncancellable

By default a thread is synchronously cancelable. When pthread_cancel is called a message is posted to the thread called and when this thread calls pthread_testcancel it gets the cancel notification. If the thread is set to asynchronously cancelable by calling pthread_setcanceltype then the calling pthread_cancel will terminate the callee. If the cancel state was set to uncancelable then pthread_cancel returns with an error.

Some Observations
There is a rather uncanny resemblance between C++ threading library and pThreads. C++ does not have semaphores just yet. Semaphores can be replaced by condition variables although it does require a change in thinking. C++ has added futures, promises and atomics. For a Windows programmer the absence of events will be noticed. There is of course no need for that given mutexes and condition variables.

Conclusion
It is a lot more easier way to write multi-threaded using the C++ threading library or its cousin pThreads that to code native Windows. The only feature I miss is IO completion ports.

 

Advertisements

About The Sunday Programmer

Joe is an experienced C++/C# developer on Windows. Currently looking out for an opening in C/C++ on Windows or Linux.
This entry was posted in Concurrent Programming, Linux, Software Engineering, Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s