Mnemonic Thread support
General Info

Introduction
Screenshots
Mailing Lists and IRC
Alternative Browsers
Special Thanks

FAQ
Understanding Mnemonic
TODO list and ideas
Bug Reports


User Info

Download binaries
Platforms
Compiling Mnemonic
Other useful software


Developer Info

Core
Message modules
Library modules
Object modules
Coding Guidelines
Browse Source
Using CVS


View with any browser

Website questions to:
webmaster@mnemonic.org

Mnemonic questions to:
disc@mnemonic.org

 

Thread support in the Mnemonic core

The thread classes (thread,thread_mutex and thread_cond) are object oriented wrappers around pthread.

The explanation of the code is simple. But the usage is not so easy. Two threads can cause segfaults or deadlock which should be prevented.

Deadlock is when one or more threads are waiting for an event which is never going to happen because the thread that should cause the event is also waiting for something.

A race is a position in the code where it is possible to create deadlock.

A segfault is caused by an incorrect memory access. When multiple threads have access to the same data then it is really easy to access by accident memory that was never allocated or already freed.

See also the ptr class (reference counting) for a method to protect memory. The ptr class keeps the data allocated until nobody is using it anymore.

The thread class

Threads create a second process which runs at the same time in the same data. The thread class tries to create an easy interface to the pthread routines. The public interface is

class thread {
   public:
      thread(void);
      virtual     ~thread();
      void         start(void);
      void         stop(void);
      virtual void begin(void)=0;
      virtual void cancel();
};

You should implement the begin method (which must contain the code that has to run in the thread). When it returns the thread stops running. If you need anything special when this thread is requested to terminate, also override the cancel method. In particular, if your thread can exit upon request, you should set a flag in the cancel which is periodically checked in the begin method loop (see http_thread.cc in mnemonic-oil-httphandler for an example).

The parent process that wants to start a new thread does so by calling the start method. When it wants the thread to terminate, it has to call the stop method (even if you know that the thread has already ended). The stop method suspends the parent process until the thread has fully ended (ie. it is a synchronous stop).

The cancel routine is intended as a general way to signal a thread that it should stop. The code should check from time to time if someone has called cancel. One way to do that is by setting a flag with the cancel routine and checking the flag in the rest of the code.

The thread_mutex class

A mutex is a method to prevent two threads changing the same data. In some cases that is not a problem, but there are where it is a problem. Examples are pointers and counters. Mutexes easily create deadlocks. Classic problems with mutexes are when it is tried to lock a locked mutex or that two locked mutexes are waiting for each other to unlock.

The lock routine locks the mutex. When a mutex it is locked it cannot locked again. So when another thread tries to lock it, it will wait till the mutex is unlocked.

The trylock routine tries to lock the mutex. If it succeeds it returns 0 else it returns EBUSY.

The unlock unlocks the mutex. A lock may only unlocked from the same thread.

The thread_condition class

A condition is a complexer method of data protection. It is used to make sure that an event has happend before the next event is started. A condition has the same functionality as the mutex but a bit more.

An example of the usage of a condition is when you are using two threads and want to start the other thread and have the other wait till it is done. If you just try to lock in thread 1 then try to lock in thread 2, next unlock in thread 1, relock in thread 1 then it is not certain that thread 2 will run in the time between the unlock and the lock. The condition gives you the possibility to resolve this by making thread 1 wait and when thread 2 is done it can signal thread 1 to start again.

The wait routine should be called with the mutex of the condition locked. It unlocks the mutex and waits till broadcast or signal is called. When that has happened it relocks the mutex and returns. Example:

thread_cond cond;
int x, y;

cond.lock();
while(x < y)
   cond.wait();
cond.unlock();

The broadcast routine restarts all on this condition waiting threads. Usually the mutex is locked before calling this routine to make sure that the other threads are waiting, and not somewhere before that point.

The signal routine restarts one of the on this condition waiting threads, which thread is not defined.