• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

sst/elements/genericProc/programs/libcprops/thread.h

Go to the documentation of this file.
00001 #ifndef _CP_THREAD_H
00002 #define _CP_THREAD_H
00003 
00004 /**
00005  * @addtogroup cp_thread
00006  */
00007 /** @{ */
00008 /** 
00009  * @file
00010  * definitions for the thread management framework. the
00011  * current implementation is based on the POSIX thread api. 
00012  */
00013 
00014 #include "common.h"
00015 
00016 __BEGIN_DECLS
00017 
00018 #include "config.h"
00019 /* synchronization api abstraction (a bunch of pthread-like macros basically)
00020  * is in collection.h
00021  */
00022 #include "collection.h"
00023 #include "linked_list.h"
00024 #include "hashlist.h"
00025 #include "vector.h"
00026 
00027 /** a thread function */
00028 typedef void *(*cp_thread_action) (void *);
00029 
00030 
00031 /** a stop function for client threads */
00032 typedef int (*cp_thread_stop_fn)(void *);
00033 
00034 /**
00035  * cp_pooled_thread is a thread that lives in a thread_pool. The struct holds 
00036  * synchronization elements used to control the thread and actuation settings, 
00037  * i.e. a thread function and a parameter to be passed for the next starting 
00038  * thread. The pool initializes a bunch of threads and sets them in 'wait'. 
00039  *
00040  * When a client requests threads from the pool, the next available thread is
00041  * signalled out of 'wait', and runs the thread function requested by the 
00042  * client (see cp_thread_pool_get_impl). When the client thread function is 
00043  * done, the cp_pooled_thread returns to the thread pool and becomes available 
00044  * to pool clients. The cp_pooled_thread only exits when the pool exits, unless
00045  * explicitly stopped (eg pthread_exit) by client code. 
00046  */ 
00047 typedef CPROPS_DLL struct _cp_pooled_thread
00048 {
00049         long id;                                                ///< integral (implementation specific) thread id
00050         struct _cp_thread_pool *owner;  ///< the pool this thread belongs to
00051         cp_thread *worker;                              ///< the actual thread
00052         cp_thread_action action;                ///< thread function for the next assignment
00053         void *action_prm;                               ///< parameter for the next assignment
00054         cp_thread_stop_fn stop_fn;              ///< called on cp_pooled_thread_stop
00055         void *stop_prm;                                 ///< if not set, stop_fn invoked w/ action_prm
00056 
00057         cp_mutex *suspend_lock;                 ///< lock for framework scheduling
00058         cp_cond *suspend_cond;                  ///< condition variable for framework scheduling
00059 
00060         int done;                                               ///< done flag
00061         int wait;                                               ///< wait flag
00062 } cp_pooled_thread;
00063 
00064 /** return a thread id for this thread */
00065 CPROPS_DLL
00066 long cp_pooled_thread_get_id(cp_pooled_thread *thread);
00067 
00068 /** thread constructor function */
00069 CPROPS_DLL
00070 cp_pooled_thread *cp_pooled_thread_create(struct _cp_thread_pool *owner);
00071 
00072 /** thread destructor */
00073 CPROPS_DLL
00074 void cp_pooled_thread_destroy(cp_pooled_thread *t);
00075 
00076 /** signal a thread to stop */
00077 CPROPS_DLL
00078 int cp_pooled_thread_stop(cp_pooled_thread *t);
00079 
00080 /** retrieve an integer type thread id for this thread */
00081 CPROPS_DLL
00082 long cp_pooled_thread_get_id(cp_pooled_thread *t);
00083 
00084 /** sets the action and prm for this thread, then invokes 'action' */
00085 CPROPS_DLL
00086 int cp_pooled_thread_run_task(cp_pooled_thread *pt, 
00087                                                           cp_thread_action action, 
00088                                                           void *prm);
00089 
00090 /** perform action with stop function */
00091 CPROPS_DLL
00092 int cp_pooled_thread_run_stoppable_task(cp_pooled_thread *pt, 
00093                                                                                 cp_thread_action action,
00094                                                                                 void *action_prm,
00095                                                                                 cp_thread_stop_fn stop_fn,
00096                                                                                 void *stop_prm);
00097 
00098 /** framework thread function */
00099 CPROPS_DLL
00100 void *cp_pooled_thread_run(void *prm);
00101         
00102 
00103 /** 
00104  * cp_thread_pool holds a list of free threads (in wait mode). The list grows 
00105  * up to max_size, after which subsequent calls to cp_thread_pool_get will 
00106  * block, and calls to cp_thread_pool_get_nb will return NULL - until clients 
00107  * return their threads to the pool. 
00108  */
00109 typedef CPROPS_DLL struct _cp_thread_pool
00110 {
00111         int size;                               ///< current size
00112 
00113         int min_size;                   ///< initial size
00114         int max_size;                   ///< size limit
00115 
00116         int running;
00117 
00118         cp_mutex *pool_lock;    ///< to sync thread assignment and release
00119         cp_cond *pool_cond;             ///< to sync thread assignment and release
00120 
00121         cp_list *free_pool;             ///< holder for unused threads
00122         cp_hashlist *in_use;    ///< holder for running threads
00123 } cp_thread_pool;
00124 
00125 /** cp_thread_pool constructor */
00126 CPROPS_DLL
00127 cp_thread_pool *cp_thread_pool_create(int min_size, int max_size);
00128 
00129 /** cp_thread_pool destructor */
00130 CPROPS_DLL
00131 void cp_thread_pool_destroy(cp_thread_pool *pool);
00132 
00133 /** wait for threads to finish processing client requests */
00134 CPROPS_DLL
00135 int cp_thread_pool_wait(cp_thread_pool *pool);
00136 
00137 /** signal all threads in this pool to stop */
00138 CPROPS_DLL
00139 int cp_thread_pool_stop(cp_thread_pool *pool);
00140 
00141 /** 
00142  * request a thread from the pool. If no threads are available, this function
00143  * will block until a thread becomes available.
00144  */
00145 CPROPS_DLL 
00146 cp_thread *cp_thread_pool_get(cp_thread_pool *pool, 
00147                                                           cp_thread_action action, 
00148                                                           void *prm);
00149 
00150 /** 
00151  * request a thread from the pool. If no threads are available, this function
00152  * will block until a thread becomes available.
00153  */
00154 CPROPS_DLL 
00155 cp_thread *cp_thread_pool_get_stoppable(cp_thread_pool *pool, 
00156                                                                                 cp_thread_action action, 
00157                                                                                 void *action_prm, 
00158                                                                                 cp_thread_stop_fn stop_fn,
00159                                                                                 void *stop_prm);
00160 
00161 /** 
00162  * request a thread from the pool - non-blocking version. Returns a pointer 
00163  * to the requested thread if one is available or NULL if the pool is empty. 
00164  */
00165 CPROPS_DLL 
00166 cp_thread *cp_thread_pool_get_nb(cp_thread_pool *pool, 
00167                                                                  cp_thread_action action, 
00168                                                                  void *prm);
00169 /** 
00170  * request a thread from the pool - non-blocking version. Returns a pointer 
00171  * to the requested thread if one is available or NULL if the pool is empty. 
00172  */
00173 CPROPS_DLL 
00174 cp_thread *cp_thread_pool_get_stoppable_nb(cp_thread_pool *pool, 
00175                                                                   cp_thread_action action, 
00176                                                                   void *action_prm,
00177                                                                   cp_thread_stop_fn stop_fn,
00178                                                                   void *stop_prm);
00179 
00180 /** returns the number of available threads in the pool. */
00181 CPROPS_DLL 
00182 int cp_thread_pool_count_available(cp_thread_pool *pool);
00183 
00184 /* **************************************************************************
00185  *                                                                          *
00186  *                      thread management framework                         *
00187  *                                                                          *
00188  ************************************************************************** */
00189 
00190 
00191 /**
00192  * Definitions for thread management framework follow. The framework is based
00193  * on the cp_thread_pool and cp_pooled_thread types. 
00194  * <br>
00195  * The pooled thread scheduler interface is meant for use by clients who 
00196  * require a variable number of threads. Each such component should create 
00197  * an instance of cp_pooled_thread_client_interface and use the api functions
00198  * to get threads from the underlying cp_thread_pool. Here is some example
00199  * code. 
00200  * <p><tt><code><pre>
00201  * cp_pooled_thread_scheduler *main_scheduler; 
00202  * 
00203  * ...
00204  *
00205  * component_a_start(component_a *a, ...)
00206  * {
00207  *     a->scheduler_interface = 
00208  *         cp_pooled_thread_client_interface_create(main_scheduler, a, 2, 10, 
00209  *             component_a_report_load, component_a_stop_thread, 
00210  *             component_a_thread_run, a);
00211  * 
00212  *     ...
00213  * 
00214  *     for (i = 0; i < a->scheduler_interface->min; i++)
00215  *         cp_pooled_thread_client_get(a->scheduler_interface);
00216  * }
00217  *
00218  * component_b_start(component_b *b, ...)
00219  * {
00220  *     b->scheduler_interface = 
00221  *         cp_pooled_thread_client_interface_create(main_scheduler, b, 2, 10, 
00222  *             component_a_report_load, component_a_stop_thread, 
00223  *             component_a_thread_run, b);
00224  * 
00225  *     ...
00226  * 
00227  *     for (i = 0; i < b->scheduler_interface->min; i++)
00228  *         cp_pooled_thread_client_get(b->scheduler_interface);
00229  * }
00230  * 
00231  * </tt></code></pre><br>
00232  * In this example, the threads for component_a and component_b will be 
00233  * managed jointly, since their cp_pooled_thread_client_interface *'s have the 
00234  * same cp_pooled_thread_scheduler *. <p>
00235  * 
00236  * 
00237  * See cp_pooled_thread_client_negociate for details. 
00238  */
00239 typedef CPROPS_DLL struct cp_pooled_thread_scheduler
00240 {
00241         cp_thread_pool *pool; ///< pool to operate on
00242         cp_vector *client_list; ///< list of clients
00243         int bypass; ///< when bypass flag set 'negociate' function becomes nop
00244 } cp_pooled_thread_scheduler;
00245 
00246 CPROPS_DLL struct _cp_pooled_thread_client_interface;
00247 
00248 typedef int (*cp_pooled_thread_report_load) //~~ change prm to void *client
00249         (struct _cp_pooled_thread_client_interface *s);
00250 typedef void (*cp_pooled_thread_shrink) //~~ change prm to void *client
00251         (struct _cp_pooled_thread_client_interface *);
00252 
00253 /**
00254  * cp_pooled_thread_client_interface acts as the link to the 
00255  * cp_pooled_thread_scheduler for clients that require a variable number of 
00256  * threads. This interface holds 3 functions pointers that must be supplied
00257  * by a client: <br>
00258  * <li> report_load - should return the number of open requests the client has
00259  * to handle
00260  * <li> shrink - will be called by the framework to stop one client thread 
00261  * <li> action - the thread function for this client
00262  */
00263 typedef CPROPS_DLL struct _cp_pooled_thread_client_interface
00264 {
00265         int max;        ///< thread count upper limit 
00266         int min;        ///< thread count bottom limit
00267 
00268         int count;      ///< actual number of threads serving this client
00269 
00270         void *client;   ///< pointer to client
00271         cp_pooled_thread_scheduler *owner;      ///< pointer to thread_pool_scheduler
00272         cp_pooled_thread_report_load report_load; ///< client function to report load
00273         cp_pooled_thread_shrink shrink; ///< client function to stop 1 thread
00274         cp_thread_action action; ///< client thread function 
00275         void *action_prm; ///< parameter to client thread function (usually == client)
00276         cp_thread_stop_fn stop_fn; ///< stop callback 
00277         void *stop_prm; ///< parameter to stop callback - if NULL action_prm will be used
00278 } cp_pooled_thread_client_interface;
00279 
00280 /** cp_pooled_thread_client_interface constructor */
00281 CPROPS_DLL
00282 cp_pooled_thread_client_interface *
00283         cp_pooled_thread_client_interface_create
00284                 (cp_pooled_thread_scheduler *owner, 
00285                  void *client, 
00286                  int min_threads, 
00287                  int max_threads,
00288                  cp_pooled_thread_report_load report_load,
00289                  cp_pooled_thread_shrink shrink,
00290                  cp_thread_action action,
00291                  void *action_prm,
00292                  cp_thread_stop_fn stop_fn,
00293                  void *stop_prm);
00294 
00295 /** cp_pooled_thread_client_interface destructor */
00296 CPROPS_DLL
00297 void cp_pooled_thread_client_interface_destroy
00298         (cp_pooled_thread_client_interface *client);
00299 
00300 /**
00301  * threads should call negociate when a change in the number of threads a 
00302  * client owns is required. 
00303  * Two possible scheduling approaches are -
00304  * 
00305  * (1) centralized:
00306  *     Clients report their load factor to the thread manager. The thread 
00307  *     manager grants requests for new threads to clients with higher loads
00308  *     first. 
00309  * 
00310  * (2) distributed:
00311  *     clients negociate with other clients requesting a thread based on their
00312  *     load factors. The client with the lower load factor releases a thread 
00313  *     to the client with the higher load factor. 
00314  * 
00315  * The distributed approach saves some bookkeeping over head in the thread 
00316  * manager, reduces the number steps involved in acquiring a new thread or
00317  * releasing an unused one, and makes a dedicated synchronization thread 
00318  * unnecessary. <p>
00319  * 
00320  * In the current implementation, the scheduler will randomly choose one 
00321  * other client to negociate with. If the load factors are different enough, 
00322  * one thread will be switched to the busier client.
00323  */
00324 CPROPS_DLL
00325 void cp_pooled_thread_client_negociate(cp_pooled_thread_client_interface *c);
00326 
00327 /** cp_pooled_thread_scheduler constructor */
00328 CPROPS_DLL
00329 cp_pooled_thread_scheduler *cp_pooled_thread_scheduler_create(cp_thread_pool *pool);
00330 
00331 /** cp_pooled_thread_scheduler destructor */
00332 CPROPS_DLL
00333 void cp_pooled_thread_scheduler_destroy(cp_pooled_thread_scheduler *scheduler);
00334 
00335 /** register client as a client of this scheduler */
00336 CPROPS_DLL
00337 void cp_pooled_thread_scheduler_register_client
00338                 (cp_pooled_thread_scheduler *scheduler, 
00339                  cp_pooled_thread_client_interface *client);
00340 
00341 /** 
00342  * convenience to abstract cp_thread_pool based implementation, see 
00343  * cp_pooled_thread_get and cp_pooled_thread_get_nb
00344  */
00345 CPROPS_DLL 
00346 void cp_pooled_thread_client_get(cp_pooled_thread_client_interface *c);
00347 
00348 /** 
00349  * convenience to abstract cp_thread_pool based implementation, see 
00350  * cp_pooled_thread_get and cp_pooled_thread_get_nb
00351  */
00352 CPROPS_DLL 
00353 void cp_pooled_thread_client_get_stoppable(cp_pooled_thread_client_interface *c);
00354 
00355 /** 
00356  * convenience to abstract cp_thread_pool based implementation, see 
00357  * cp_pooled_thread_get and cp_pooled_thread_get_nb
00358  */
00359 CPROPS_DLL 
00360 void cp_pooled_thread_client_get_nb(cp_pooled_thread_client_interface *c);
00361 
00362 /** 
00363  * convenience to abstract cp_thread_pool based implementation, see 
00364  * cp_pooled_thread_get and cp_pooled_thread_get_nb
00365  */
00366 CPROPS_DLL 
00367 void cp_pooled_thread_client_get_stoppable_nb(cp_pooled_thread_client_interface *c);
00368 
00369 __END_DECLS
00370 
00371 /** @} */
00372 
00373 #endif /* _CP_THREAD */
00374 

Generated on Fri Oct 22 2010 11:02:22 for SST by  doxygen 1.7.1