lobot::Thread Class Reference

An ABC for POSIX threads. More...

#include <Robots/LoBot/thread/LoThread.H>

Inheritance diagram for lobot::Thread:
Inheritance graph
[legend]
Collaboration diagram for lobot::Thread:
Collaboration graph
[legend]

List of all members.

Public Member Functions

pthread_t id () const
 Return this thread's ID.
const std::stringname () const
 Return this thread's name.
bool running () const
 Check if the thread is actually running.
virtual void run ()=0
virtual ~Thread ()
 Clean-up.

Static Public Member Functions

static int count ()
 Return the current number of extant threads.
static void wait_all ()

Protected Member Functions

 Thread ()
void start (const std::string &name, bool thread_func_returns_normally=true)

Detailed Description

An ABC for POSIX threads.

lobot::Thread is an abstract base class for creating threads to handle different tasks within the Robolocust system. It wraps around some of the basic creation and management APIs of the POSIX threads library and provides some additional custom support on top of that.

In terms of the additional custom support alluded to above, specifically, this class keeps track of the number of threads currently running and allows the main thread to wait for all the other threads to die with one convenient API.

Robolocust modules that need to create new threads should use this class rather than the raw pthreads API. However, only some basic thread creation and management functions are implemented. This means that clients have to either fall back on the raw POSIX API or rely on some other wrapper classes for mutexes, condition variables, etc.

To use this class, simply derive from it and define the run() method. Then, instantiating the derived class will take care of the mechanics of creating the thread, keeping track of it, etc.

An important thing to keep in mind when using this class is that the threads it creates are detached, i.e., it is not possible for another thread to execute pthread_join() on the thread. This ensures that all thread resources are immediately cleaned up by the OS when the thread exits. Naturally, it also prevents other threads from joining with it.

The rationale for this design choice is as follows: the Robolocust system maintains a central shutdown object that signals all the threads that it's time to wind-up. Each Robolocust thread is required to monitor the state of this shutdown object in its main loop and take appropriate action to gracefully kill itself when the shutdown object is in the signaled state. Additionally, when shutdown is signaled, the main thread waits for all the other threads to die and then exits the application. Thus, there is no need for any thread to wait for another by joining with it.

NOTE: This class does not prevent clients from creating instances on the stack (i.e., as local variables). However, doing that would generally be a Bad Idea because when the local object goes out of scope, its run() method will no longer be available, which, most likely, will cause all hell to break loose.

DEVNOTE: We could use the named constructor idiom to require clients to always create Thread objects with the new operator. However, that precludes using this class in conjunction with lobot::singleton, which is why we don't enforce the do-not-create-on-stack policy.

Definition at line 130 of file LoThread.H.


Constructor & Destructor Documentation

lobot::Thread::Thread (  )  [protected]

A protected constructor because clients should not be able to directly instantiate this class.

Definition at line 101 of file LoThread.C.

lobot::Thread::~Thread (  )  [virtual]

Clean-up.

Definition at line 179 of file LoThread.C.


Member Function Documentation

int lobot::Thread::count (  )  [static]

Return the current number of extant threads.

Definition at line 160 of file LoThread.C.

Referenced by lobot::Shutdown::start_listening().

pthread_t lobot::Thread::id (  )  const [inline]

Return this thread's ID.

Definition at line 144 of file LoThread.H.

const std::string& lobot::Thread::name (  )  const [inline]

Return this thread's name.

Definition at line 147 of file LoThread.H.

Referenced by lobot::Behavior::run().

virtual void lobot::Thread::run (  )  [pure virtual]

This method implements the thread's custom processing. It must be defined by every subclass.

Implemented in lobot::Arbiter, and lobot::Behavior.

bool lobot::Thread::running (  )  const [inline]

Check if the thread is actually running.

Definition at line 150 of file LoThread.H.

Referenced by lobot::Shutdown::signal(), lobot::Shutdown::signaled(), and lobot::Arbiter::vote().

void lobot::Thread::start ( const std::string name,
bool  thread_func_returns_normally = true 
) [protected]

Creating a new thread object doesn't automatically start the thread running. Derived classes *must* call this method in the body of their constructors (usually, towards the end). The reason for this two-step procedure is due to the fact that the thread function implemented in this base class calls the run() method in the derived class. For this to work properly, the derived class object must be fully constructed with its v-table setup for action. If we were to start the new thread running in this class's constructor, it can happen that Thread::thread_func() will crash when it attempts to invoke the pure virtual run() method.

Therefore, *all* derived class constructors *must* include a call to Thread::start(). By the time we get into a constructor's body, we can be assured that the object is fully constructed and its v-table properly setup. This ensures that Thread::thread_func() will be able to use the virtual function mechanism to call into the derived class's run() method.

Note, however, that client modules do not see this two-step thread creation procedure. A client module simply creates an instance of a Thread subclass without having to fuss around with anything else. Once the instance is created, the thread will automatically start running. The onus here is on subclasses to ensure that this automatic thread creation and starting business actually works from the point of view of client modules.

Usually, a derived class's run() method will implement some sort of "main" loop and when that loop exits, the run() method will return. However, in some situations, the main loop may be implemented externally (e.g., glutMainLoop()). Threads that implement run() methods that don't return normally should pass false as the second parameter to Thread::start().

Definition at line 105 of file LoThread.C.

void lobot::Thread::wait_all (  )  [static]

Wait for all the extant threads to die.

NOTE: This method is meant to be called *only* by the main thread.

Definition at line 169 of file LoThread.C.


The documentation for this class was generated from the following files:
Generated on Sun May 8 08:44:35 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3