Various C++ Examples (including IPC)  Version: 1.0.0
ThreadMgr Class Reference

A basic thread management class. More...

Collaboration diagram for ThreadMgr:
Collaboration graph

Classes

struct  func_arguments
 structure for static wrapper function arguments More...
 

Public Member Functions

 ThreadMgr ()
 constructor More...
 
int cancel_thread (pthread_t *tid)
 cancel a thread More...
 
int condWait (void **thread_return_val)
 wait on a condition variable for a thread to terminate More...
 
pthread_t createThread (void *(*thread_func)(void *), void *arg)
 attempt to create a new thread and register it More...
 
int threadsActive ()
 return the number of active threads More...
 
bool no_threads_terminated ()
 answers the question "are there no theads terminated?" More...
 

Protected Member Functions

int removeTerminated (void **return_val)
 remove a terminated thread LIFO More...
 
void addID (pthread_t id, func_arguments *arg)
 add a thread id to the id vector More...
 

Static Protected Member Functions

static void * func (void *arg)
 internal thread function More...
 
static void * addTerminated (ThreadMgr *arg)
 add a thread id to the m_terminated stack More...
 
static void shutdown_thread (void *arg)
 shutdown a thread from pthread_cleanup_pop(). More...
 

Private Attributes

pthread_mutex_t * m_mutex
 mutex for data access (m_ids, m_terminated) More...
 
pthread_mutex_t * m_cond_mutex
 mutex for condition variable More...
 
pthread_cond_t * m_cond_var
 condition variable More...
 
std::map< pthread_t, ThreadMgr::func_arguments * > m_ids
 map of all thread ids and function attributes More...
 
std::stack< pthread_t > m_terminated
 stack of terminated thread ids More...
 

Detailed Description

A basic thread management class.

Author
Karl N. Redman (karl..nosp@m.redm.nosp@m.an@gm.nosp@m.ail..nosp@m.com)
Purpose:
This is an example class intended to be used as a guidline for the work required to handle pthreads where the main process (the parent of the initial threads) waits on a condition variable for the threads to terminate. The functions that are specified for the pthread_create are user defined.

This class should be pretty fast and relatively easy to use for most general purpose thread programming. In general, it's a good place to start.

Basic pthread "voidness" has been retained for demonstration purposes. It is concevable that this class could be instantiated from and / or altered to make the user interface easier to work with (in other words -we could get rid of much of the user end casting through inheritance).
Note
This class is not intended for use by detached threads unless some of the functions are overridden. Also, the use of long casting was used in favor of readability in the interests of speed.

Definition at line 60 of file threadDeath3.cc.

Constructor & Destructor Documentation

ThreadMgr::ThreadMgr ( )
inline

constructor

Note
this function instantiates static pthread_x_t variables for mutexes and a condition variable

Definition at line 80 of file threadDeath3.cc.

References m_cond_mutex, m_cond_var, and m_mutex.

81  {
86  //the data mutex
87  static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
88  m_mutex = &mutex;
89 
90  //the condition variable mutex
91  static pthread_mutex_t cond_mutex = PTHREAD_MUTEX_INITIALIZER;
92  m_cond_mutex = &cond_mutex;
93 
94  //the condition variable
95  static pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
96  m_cond_var = &cond_var;
97  }
pthread_cond_t * m_cond_var
condition variable
pthread_mutex_t * m_mutex
mutex for data access (m_ids, m_terminated)
pthread_mutex_t * m_cond_mutex
mutex for condition variable

Member Function Documentation

void ThreadMgr::addID ( pthread_t  id,
func_arguments arg 
)
inlineprotected

add a thread id to the id vector

Definition at line 386 of file threadDeath3.cc.

References m_ids, and m_mutex.

Referenced by createThread().

387  {
388  //lock the data mutex
389  pthread_mutex_lock(m_mutex);
390 
391  //add the thread to the std::map
392  m_ids.insert(std::make_pair(id, arg));
393 
394  //unlock the data mutex
395  pthread_mutex_unlock(m_mutex);
396  }
std::map< pthread_t, ThreadMgr::func_arguments * > m_ids
map of all thread ids and function attributes
pthread_mutex_t * m_mutex
mutex for data access (m_ids, m_terminated)
static void* ThreadMgr::addTerminated ( ThreadMgr arg)
inlinestaticprotected

add a thread id to the m_terminated stack

Definition at line 317 of file threadDeath3.cc.

References m_cond_var, m_mutex, and m_terminated.

Referenced by func().

318  {
319  //pthread_mutex_lock(((ThreadMgr *)arg)->m_mutex);
320  pthread_mutex_lock(arg->m_mutex);
321 
322  //add self to list of stuff to be terminated (joined)
323  arg->m_terminated.push(pthread_self());
324 
325  //broadcast to threads waiting on the condition variable to notify
326  //them to wake up
327  pthread_cond_broadcast(arg->m_cond_var);
328 
329  pthread_mutex_unlock(arg->m_mutex);
330 
331  //return NULL -blah
332  return NULL;
333  }
pthread_cond_t * m_cond_var
condition variable
pthread_mutex_t * m_mutex
mutex for data access (m_ids, m_terminated)
std::stack< pthread_t > m_terminated
stack of terminated thread ids
int ThreadMgr::cancel_thread ( pthread_t *  tid)
inline

cancel a thread

Returns
return value of a pthread_cancel() for parameter tid
Parameters
tidpointer to the thread id to kill
Warning
If the thread has allocated dynamic memory and has been canceled this class does not compensate. In other words, never cancel a thread (with this class) that allocates dynamic memory -you will lose your pointer. This is because pthread_cancel does not allow you to recieve anything back from a canceled thread. However, you could delete your pointer before you retrurn from the thread if that is your wish.
use of the function pthread_cancel() for threads managed by this class may result in loss of dynamic memory pointers, or worse, a race condition for m_mutex resulting in a deadlock of the threads. Don not use pthread_cancel() for threads managed by this class. Use ThreadMgr::cancel_thread() instead.
Todo:
add more robust thread canceling ability

Definition at line 100 of file threadDeath3.cc.

References m_ids, and m_mutex.

Referenced by main().

101  {
126  //cancel a thread
127  int ret = 0;
128  pthread_mutex_lock(m_mutex); //lock the data mutex
129  m_ids.erase(*tid); //remove from id map
130 
131  //cancel the thread
132  ret = pthread_cancel(*tid);
133 
134  pthread_mutex_unlock(m_mutex); // unlock data mutex
135 
136  return ret;
137  }
std::map< pthread_t, ThreadMgr::func_arguments * > m_ids
map of all thread ids and function attributes
pthread_mutex_t * m_mutex
mutex for data access (m_ids, m_terminated)
int ThreadMgr::condWait ( void **  thread_return_val)
inline

wait on a condition variable for a thread to terminate

Purpose:
Act like a seamless condition variable. Allows a process to block until a thread has terminated and returns the thread functions return value through the parameter.
Parameters
apointer to the pointer of the threads return value.
Returns
pthread_join status from removeTerminated()
Warning
This function may not be safe for threads that are canceled

Definition at line 140 of file threadDeath3.cc.

References m_cond_mutex, m_cond_var, no_threads_terminated(), and removeTerminated().

Referenced by main(), TwaitStringThreads(), and waitStringThreads().

141  {
156  int ret = 0;
157 
158  //condition variable mutex lock
159  pthread_mutex_lock(m_cond_mutex);
160 
161  //check predicate
162  while(no_threads_terminated())
163  {
164  //wait on condition variable
165  pthread_cond_wait(m_cond_var, m_cond_mutex);
166  }
167 
168 
169  //remove the thread from the terminated list (handle join)
170  ret = removeTerminated(thread_return_val);
171 
172  //unlock
173  pthread_mutex_unlock(m_cond_mutex);
174 
175  //return join status
176  return ret;
177  }
int removeTerminated(void **return_val)
remove a terminated thread LIFO
pthread_cond_t * m_cond_var
condition variable
bool no_threads_terminated()
answers the question "are there no theads terminated?"
pthread_mutex_t * m_cond_mutex
mutex for condition variable

Here is the call graph for this function:

pthread_t ThreadMgr::createThread ( void *(*)(void *)  thread_func,
void *  arg 
)
inline

attempt to create a new thread and register it

Purpose:
Create a new thread and register it for management by this class.
Returns
0 on error, pthread_t thread ID on success
Parameters
pointerto function to run as thread, pointer to argument. [i.e. createThread(myfunc, arg);]
Note
This function works by building the an argument list from the one provided by the user and some internal stuff in order to call an internal function that sets things up for return values, etc. and then calls the users function. This adds about the size of 8 (roughly) pointers to the memory usage of each thread being created -but that's the price for wanting to keep track of this stuff generically i guess.

Definition at line 181 of file threadDeath3.cc.

References addID(), ThreadMgr::func_arguments::arg, ThreadMgr::func_arguments::cancel_func, ThreadMgr::func_arguments::func, and ThreadMgr::func_arguments::thisObject.

Referenced by main().

182  {
203  pthread_t tid = 0; // Id of thread
204  int ret_val; // return value
205 
206  //arguments for the function
207  struct func_arguments *arguments = new func_arguments;
208 
209  arguments->func = thread_func; // users function
210  arguments->cancel_func = NULL; // NOT IMPLIMENTED
211  arguments->arg = arg; // users argument
212 
213  //this is the this pointer (so far, every thread get's one -eek!)
214  arguments->thisObject = this;
215 
216  //create a new thread
217  /*
218  default attributes (for now),
219  internal function, func(), calls users function,
220  arguments contain other info + user's argument.
221  */
222  ret_val = pthread_create(&tid, (pthread_attr_t *) NULL, func, (void *)arguments);
223 
224  if(ret_val == 0)
225  {
226  //register the thread and arguments in the ids map
227  addID(tid, arguments);
228 
229  //return thread id
230  return tid;
231  }
232  else
233  std::cout << "pthread_create FAIL" << std::endl;
234 
235 
236  //return 0 on error
237  return 0;
238  }
static void * func(void *arg)
internal thread function
void addID(pthread_t id, func_arguments *arg)
add a thread id to the id vector

Here is the call graph for this function:

static void* ThreadMgr::func ( void *  arg)
inlinestaticprotected

internal thread function

Purpose:
This function is called from the call to pthread_create() within member function createThread. This function handles basic thread management issues and is a wrapper around the user function -which is called from here as well.
Returns
NONE -this function shouldn't return!!! it calls pthread_exit().
Parameters
argshold be a pointer to a func_arguments structure.

Definition at line 265 of file threadDeath3.cc.

References addTerminated(), ThreadMgr::func_arguments::arg, ThreadMgr::func_arguments::cancel_func, ThreadMgr::func_arguments::func, shutdown_thread(), and ThreadMgr::func_arguments::thisObject.

266  {
280  //convenience this object
281  ThreadMgr *thisObject = ((struct func_arguments *)arg)->thisObject;
282 
283  //return argument from user function
284  void *tmpArg = NULL;
285 
286  //basic cancel stuff -should be more robust
287  struct func_arguments *cancel_arg = new func_arguments;
288  cancel_arg->cancel_func = shutdown_thread;
289  cancel_arg->func = NULL;
290  cancel_arg->arg = NULL;
291  cancel_arg->thisObject = thisObject;
292 
293  //set the cleanup function
294  pthread_cleanup_push(shutdown_thread, (void *)cancel_arg);
295 
296  //call the user's function
297  tmpArg = ((struct func_arguments *)arg)->func( ((struct func_arguments *)arg)->arg );
298  //std::cout << "func() passing \"" << *(std::string *)tmpArg << "\" to pthread_exit()" << std::endl;
299 
300  //delete (struct func_arguments *)arg;
301 
302  //pop the cleanup handler off the cleanup stack
303  //delete the arg variable list from the createThread function.
304  pthread_cleanup_pop(1);
305 
306  //add this thread to the terminated list
307  thisObject->addTerminated(thisObject);
308 
309  //exit this thread
310  pthread_exit(tmpArg);
311 
312  //we will never get here
313  return NULL;
314  }
static void * addTerminated(ThreadMgr *arg)
add a thread id to the m_terminated stack
static void shutdown_thread(void *arg)
shutdown a thread from pthread_cleanup_pop().
A basic thread management class.
Definition: threadDeath3.cc:60

Here is the call graph for this function:

bool ThreadMgr::no_threads_terminated ( )
inline

answers the question "are there no theads terminated?"

Returns
boolean of terminated threads in terminate queue

Definition at line 251 of file threadDeath3.cc.

References m_mutex, and m_terminated.

Referenced by condWait(), and main().

252  {
255  pthread_mutex_lock(m_mutex);
256  bool ret = m_terminated.empty();
257  pthread_mutex_unlock(m_mutex);
258  return ret;
259  }
pthread_mutex_t * m_mutex
mutex for data access (m_ids, m_terminated)
std::stack< pthread_t > m_terminated
stack of terminated thread ids
int ThreadMgr::removeTerminated ( void **  return_val)
inlineprotected

remove a terminated thread LIFO

Returns
result of pthread_join
Parameters
pointerto user function return value pointer
Note
the void **retrun_val is a result of the pthread_join.
Warning
the thread is unregistered only if the pthread_join was successfull. This may be a problem down the line (but VERY rare)

Definition at line 336 of file threadDeath3.cc.

References m_ids, m_mutex, and m_terminated.

Referenced by condWait().

337  {
345  int ret = 0;
346  pthread_t tempID;
347 
348  //lock critical section
349  pthread_mutex_lock(m_mutex);
350 
351  //make sure we have something
352  if(!m_terminated.empty())
353  {
354  //get id from stack
355  tempID = m_terminated.top();
356 
362  //join with the terminated thread
363  if( (ret = pthread_join(tempID, return_val)) == 0)
364  {
365  //delete the arguments (created in createThread)
366  //delete m_ids.find(tempID)->second;
367 
368  //get rid of the ID from active list
369  m_ids.erase(tempID);
370 
371  //remove id from stack
372  m_terminated.pop();
373  }
374  else
375  std::cout << "pthread_join() = " << ret << std::endl;
376  }
377 
378  //unlock critical section
379  pthread_mutex_unlock(m_mutex);
380 
381  //return value of pthread_join
382  return ret;
383  }
std::map< pthread_t, ThreadMgr::func_arguments * > m_ids
map of all thread ids and function attributes
pthread_mutex_t * m_mutex
mutex for data access (m_ids, m_terminated)
std::stack< pthread_t > m_terminated
stack of terminated thread ids
static void ThreadMgr::shutdown_thread ( void *  arg)
inlinestaticprotected

shutdown a thread from pthread_cleanup_pop().

Parameters
argmust be void * per pthread_cleanup_x()

Definition at line 399 of file threadDeath3.cc.

Referenced by func().

400  {
403  delete ((struct func_arguments *)arg);
404  return;
405  }
int ThreadMgr::threadsActive ( )
inline

return the number of active threads

Definition at line 241 of file threadDeath3.cc.

References m_ids, and m_mutex.

Referenced by main(), TwaitStringThreads(), and waitStringThreads().

242  {
243  pthread_mutex_lock(m_mutex);
244  int ret = m_ids.size();
245  pthread_mutex_unlock(m_mutex);
246 
247  return ret;
248  }
std::map< pthread_t, ThreadMgr::func_arguments * > m_ids
map of all thread ids and function attributes
pthread_mutex_t * m_mutex
mutex for data access (m_ids, m_terminated)

Member Data Documentation

pthread_mutex_t* ThreadMgr::m_cond_mutex
private

mutex for condition variable

Definition at line 413 of file threadDeath3.cc.

Referenced by condWait(), and ThreadMgr().

pthread_cond_t* ThreadMgr::m_cond_var
private

condition variable

Definition at line 416 of file threadDeath3.cc.

Referenced by addTerminated(), condWait(), and ThreadMgr().

std::map<pthread_t, ThreadMgr::func_arguments *> ThreadMgr::m_ids
private

map of all thread ids and function attributes

Definition at line 419 of file threadDeath3.cc.

Referenced by addID(), cancel_thread(), removeTerminated(), and threadsActive().

pthread_mutex_t* ThreadMgr::m_mutex
private

mutex for data access (m_ids, m_terminated)

Definition at line 410 of file threadDeath3.cc.

Referenced by addID(), addTerminated(), cancel_thread(), no_threads_terminated(), removeTerminated(), ThreadMgr(), and threadsActive().

std::stack<pthread_t> ThreadMgr::m_terminated
private

stack of terminated thread ids

Definition at line 422 of file threadDeath3.cc.

Referenced by addTerminated(), no_threads_terminated(), and removeTerminated().


The documentation for this class was generated from the following file: