Back to index

lightning-sunbird  0.9+nobinonly
pthread.h
Go to the documentation of this file.
00001 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
00002 // % Project  :      GUSI                        -      Grand Unified Socket Interface                    
00003 // % File            :      GUSIPThread.nw              -      Pthreads wrappers                           
00004 // % Author   :      Matthias Neeracher                                           
00005 // % Language :      C++                                                        
00006 // %                                                                       
00007 // % $Log: pthread.h,v $
00008 // % Revision 1.1  2001/03/11 22:39:05  sgehani%netscape.com
00009 // % First Checked In.
00010 // %                                              
00011 // % Revision 1.14  2001/01/17 08:55:16  neeri                             
00012 // % Detect and return ETIMEDOUT condition                                 
00013 // %                                                                       
00014 // % Revision 1.13  2000/10/29 20:31:53  neeri                             
00015 // % Releasing 2.1.3                                                       
00016 // %                                                                       
00017 // % Revision 1.12  2000/05/23 07:16:35  neeri                             
00018 // % Improve formatting, make data types opaque, tune mutexes              
00019 // %                                                                       
00020 // % Revision 1.11  2000/03/06 06:10:00  neeri                             
00021 // % Reorganize Yield()                                                    
00022 // %                                                                       
00023 // % Revision 1.10  2000/01/17 01:40:31  neeri                             
00024 // % Correct macro spelling, update references                             
00025 // %                                                                       
00026 // % Revision 1.9  1999/11/15 07:20:19  neeri                              
00027 // % Safe context setup                                                    
00028 // %                                                                       
00029 // % Revision 1.8  1999/09/09 07:22:15  neeri                              
00030 // % Add support for mutex and cond attribute creation/destruction         
00031 // %                                                                       
00032 // % Revision 1.7  1999/08/26 05:45:07  neeri                              
00033 // % Fixes for literate edition of source code                             
00034 // %                                                                       
00035 // % Revision 1.6  1999/07/07 04:17:42  neeri                              
00036 // % Final tweaks for 2.0b3                                                
00037 // %                                                                       
00038 // % Revision 1.5  1999/06/30 07:42:07  neeri                              
00039 // % Getting ready to release 2.0b3                                        
00040 // %                                                                       
00041 // % Revision 1.4  1999/05/30 03:06:55  neeri                              
00042 // % MPW compiler compatibility, recursive mutex locks                     
00043 // %                                                                       
00044 // % Revision 1.3  1999/03/17 09:05:12  neeri                              
00045 // % Added GUSITimer, expanded docs                                        
00046 // %                                                                       
00047 // % Revision 1.2  1998/08/01 21:32:10  neeri                              
00048 // % About ready for 2.0a1                                                 
00049 // %                                                                       
00050 // % Revision 1.1  1998/01/25 21:02:51  neeri                              
00051 // % Engine implemented, except for signals & scheduling                   
00052 // %                                                                       
00053 // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
00054 //                                                                         
00055 // \chapter{Pthreads Wrappers}                                             
00056 //                                                                         
00057 // As opposed to POSIX.1, with which I think I'm reasonable competent by now,
00058 // I have little practical experience, let alone in-depth familiarity with 
00059 // Pthreads, so I'm going by what I learned from                           
00060 //                                                                         
00061 // \begin{itemize}                                                         
00062 // \item Reading \emph{B.~Nicols, D.~Buttlar, and J.~Proulx Farrell,       
00063 //       ``Pthreads Programming'', O'Reilly \& Associates} and             
00064 //       \emph{D.~Butenhof, ``Programming with POSIX Threads'', Addison Wesley}.
00065 //                                                                            
00066 // \item Taking a few glimpses at Chris Provenzano's pthreads implementation.
00067 // \item Reading the news:comp.programming.threads newsgroup.              
00068 // \end{itemize}                                                           
00069 //                                                                         
00070 // If you believe that I've misunderstood Pthreads in my implementation, feel free
00071 // to contact me.                                                          
00072 //                                                                         
00073 // As opposed to most other modules, the header files we're generating here don't
00074 // have GUSI in its name.                                                  
00075 //                                                                         
00076 // <pthread.h>=                                                            
00077 #ifndef _PTHREAD_H_
00078 #define _PTHREAD_H_
00079 
00080 #include <sys/cdefs.h>
00081 #include <sys/types.h>
00082 #include <sys/time.h>
00083 
00084 __BEGIN_DECLS
00085 // \section{Definition of Pthread data types}                              
00086 //                                                                         
00087 // I used to be fairly cavalier about exposing internal GUSI data structures, 
00088 // on second thought this was not a good idea. To keep C happy, we define  
00089 // [[struct]] wrappers for what ultimately will mostly be classes.         
00090 //                                                                         
00091 // <Pthread data types>=                                                   
00092 typedef struct GUSIPThread *       pthread_t;
00093 // A [[pthread_attr_t]] collects thread creation attributes. This is implemented
00094 // as a pointer so it's easier to change the size of the underlying data structure.
00095 //                                                                         
00096 // <Pthread data types>=                                                   
00097 typedef struct GUSIPThreadAttr     * pthread_attr_t;
00098 // A [[pthread_key_t]] is a key to look up thread specific data.           
00099 //                                                                         
00100 // <Pthread data types>=                                                   
00101 typedef struct GUSIPThreadKey *    pthread_key_t;
00102 // A [[pthread_once_t]] registers whether some routine has run once. It must always
00103 // be statically initialized to [[PTHREAD_ONCE_INIT]] (Although in our implementation,
00104 // it doesn't matter).                                                     
00105 //                                                                         
00106 // <Pthread data types>=                                                   
00107 typedef char  pthread_once_t;
00108 
00109 enum {
00110        PTHREAD_ONCE_INIT = 0
00111 };
00112 // A [[pthread_mutex_t]] is a mutual exclusion variable, implemented as a pointer
00113 // to a [[GUSIContextQueue]]. For initialization convenience, a 0 value means 
00114 // an unlocked mutex. No attributes are supported so far.                  
00115 //                                                                         
00116 // <Pthread data types>=                                                   
00117 typedef struct GUSIPThreadMutex *  pthread_mutex_t;
00118 typedef void *                                          pthread_mutexattr_t;
00119 
00120 #define       PTHREAD_MUTEX_INITIALIZER   0
00121 // A [[pthread_cond_t]] is a condition variable, which looks rather similar
00122 // to a mutex, but has different semantics. No attributes are supported so far.
00123 //                                                                         
00124 // <Pthread data types>=                                                   
00125 typedef struct GUSIPThreadCond *   pthread_cond_t;
00126 typedef void *                                          pthread_condattr_t;
00127 
00128 #define PTHREAD_COND_INITIALIZER   0
00129 // [[pthread_attr_init]] initializes an attribute object with the          
00130 // default values.                                                         
00131 //                                                                         
00132 // <Pthread function declarations>=                                        
00133 int pthread_attr_init(pthread_attr_t * attr);
00134 // [[pthread_attr_destroy]] destroys an attribute object.                  
00135 //                                                                         
00136 // <Pthread function declarations>=                                        
00137 int pthread_attr_destroy(pthread_attr_t * attr);
00138 // The detach state defines whether a thread will be defined joinable or   
00139 // detached.                                                               
00140 //                                                                         
00141 // <Pthread function declarations>=                                        
00142 enum {
00143        PTHREAD_CREATE_JOINABLE,
00144        PTHREAD_CREATE_DETACHED
00145 };
00146 
00147 int pthread_attr_getdetachstate(const pthread_attr_t * attr, int * state);
00148 int pthread_attr_setdetachstate(pthread_attr_t * attr, int state);
00149 // The stack size defines how much stack space will be allocated. Stack overflows
00150 // typically lead to utterly nasty crashes.                                
00151 //                                                                         
00152 // <Pthread function declarations>=                                        
00153 int pthread_attr_getstacksize(const pthread_attr_t * attr, size_t * size);
00154 int pthread_attr_setstacksize(pthread_attr_t * attr, size_t size);
00155 // \section{Creation and Destruction of PThreads}                          
00156 //                                                                         
00157 // First, we define wrapper to map the different calling conventions of Pthreads 
00158 // and Macintosh threads.                                                  
00159 //                                                                         
00160 // <Pthread function declarations>=                                        
00161 __BEGIN_DECLS
00162 typedef void * (*GUSIPThreadProc)(void *);
00163 __END_DECLS
00164 // [[pthread_create]] stuffs the arguments in a [[CreateArg]] and creates the
00165 // context.                                                                
00166 //                                                                         
00167 // <Pthread function declarations>=                                        
00168 int pthread_create(
00169               pthread_t * thread, 
00170               const pthread_attr_t * attr, GUSIPThreadProc proc, void * arg);
00171 // A thread can either be detached, in which case it will just go away after it's 
00172 // done, or it can be joinable, in which case it will wait for [[pthread_join]]
00173 // to be called.                                                           
00174 //                                                                         
00175 // <Pthread function declarations>=                                        
00176 int pthread_detach(pthread_t thread);
00177 // [[pthread_join]] waits for the thread to die and optionally returns its last
00178 // words.                                                                  
00179 //                                                                         
00180 // <Pthread function declarations>=                                        
00181 int pthread_join(pthread_t thread, void **value);
00182 // [[pthread_exit]] ends the existence of a thread.                        
00183 //                                                                         
00184 // <Pthread function declarations>=                                        
00185 int pthread_exit(void *value);
00186 // \section{Pthread thread specific data}                                  
00187 //                                                                         
00188 // Thread specific data offers a possibility to quickly look up a value that may be 
00189 // different for every thread.                                             
00190 //                                                                         
00191 // [[pthread_key_create]] creates an unique key visible to all threads in a 
00192 // process.                                                                
00193 //                                                                         
00194 // <Pthread function declarations>=                                        
00195 __BEGIN_DECLS
00196 typedef void (*GUSIPThreadKeyDestructor)(void *);
00197 __END_DECLS
00198 
00199 int pthread_key_create(pthread_key_t * key, GUSIPThreadKeyDestructor destructor);
00200 // [[pthread_key_delete]] deletes a key, but does not call any destructors.
00201 //                                                                         
00202 // <Pthread function declarations>=                                        
00203 int pthread_key_delete(pthread_key_t key);
00204 // [[pthread_getspecific]] returns the thread specific value for a key.    
00205 //                                                                         
00206 // <Pthread function declarations>=                                        
00207 void * pthread_getspecific(pthread_key_t key);
00208 // [[pthread_setspecific]] sets a new thread specific value for a key.     
00209 //                                                                         
00210 // <Pthread function declarations>=                                        
00211 int pthread_setspecific(pthread_key_t key, void * value);
00212 // \section{Synchronization mechanisms of PThreads}                        
00213 //                                                                         
00214 // Since we're only dealing with cooperative threads, all synchronization  
00215 // mechanisms can be implemented using means that might look naive to a student
00216 // of computer science, but that actually work perfectly well in our case. 
00217 //                                                                         
00218 // We currently don't support mutex and condition variable attributes. To minimize
00219 // the amount of code changes necessary inclients, we support creating and destroying
00220 // them, at least.                                                         
00221 //                                                                         
00222 // <Pthread function declarations>=                                        
00223 int pthread_mutexattr_init(pthread_mutexattr_t * attr);
00224 int pthread_mutexattr_destroy(pthread_mutexattr_t * attr);
00225 // <Pthread function declarations>=                                        
00226 int pthread_mutex_init(pthread_mutex_t * mutex, const pthread_mutexattr_t *);
00227 int pthread_mutex_destroy(pthread_mutex_t * mutex);
00228 // Lock may create the queue if it was allocated statically. Mutexes are implemented
00229 // as a queue of context, with the frontmost context holding the lock. Simple enough,
00230 // isn't it?                                                               
00231 //                                                                         
00232 // <Pthread function declarations>=                                        
00233 int pthread_mutex_lock(pthread_mutex_t * mutex);
00234 // Strangely enough, [[pthread_mutex_trylock]] is much more of a problem if we want 
00235 // to maintain a semblance of scheduling fairness. In particular, we need the [[Yield]]
00236 // in case somebody checks a mutex in a loop with no other yield point.    
00237 //                                                                         
00238 // <Pthread function declarations>=                                        
00239 int pthread_mutex_trylock(pthread_mutex_t * mutex);
00240 // Unlocking pops us off the queue and wakes up the new lock owner.        
00241 //                                                                         
00242 // <Pthread function declarations>=                                        
00243 int pthread_mutex_unlock(pthread_mutex_t * mutex);
00244 // On to condition variable attributes, which we don't really support either.
00245 //                                                                         
00246 // <Pthread function declarations>=                                        
00247 int pthread_condattr_init(pthread_condattr_t * attr);
00248 int pthread_condattr_destroy(pthread_condattr_t * attr);
00249 // Condition variables in some respects work very similar to mutexes.      
00250 //                                                                         
00251 // <Pthread function declarations>=                                        
00252 int pthread_cond_init(pthread_cond_t * cond, const pthread_condattr_t *);
00253 int pthread_cond_destroy(pthread_cond_t * cond);
00254 // [[pthread_cond_wait]] releases the mutex, sleeps on the condition variable,
00255 // and reacquires the mutex.                                               
00256 //                                                                         
00257 // <Pthread function declarations>=                                        
00258 int pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex);
00259 // [[pthread_cond_timedwait]] adds a timeout value (But it still could block
00260 // indefinitely trying to reacquire the mutex). Note that the timeout specifies
00261 // an absolute wakeup time, not an interval.                               
00262 //                                                                         
00263 // <Pthread function declarations>=                                        
00264 int pthread_cond_timedwait(
00265               pthread_cond_t * cond, pthread_mutex_t * mutex, 
00266               const struct timespec * patience);
00267 // [[pthread_cond_signal]] wakes up a context from the queue. Since we typically
00268 // still hold the associated mutex, it would be a bad idea (though not a disastrous
00269 // one) to put a yield in here.                                            
00270 //                                                                         
00271 // <Pthread function declarations>=                                        
00272 int pthread_cond_signal(pthread_cond_t * cond);
00273 // [[pthread_cond_broadcast]] wakes up a the entire queue (but only one context
00274 // will get the mutex).                                                    
00275 //                                                                         
00276 // <Pthread function declarations>=                                        
00277 int pthread_cond_broadcast(pthread_cond_t * cond);
00278 // \section{Pthread varia}                                                 
00279 //                                                                         
00280 // [[pthread_self]] returns the current thread.                            
00281 //                                                                         
00282 // <Pthread function declarations>=                                        
00283 pthread_t pthread_self(void);
00284 // [[pthread_equal]] compares two thread handles.                          
00285 //                                                                         
00286 // <Pthread function declarations>=                                        
00287 int pthread_equal(pthread_t t1, pthread_t t2);
00288 // [[pthread_once]] calls a routines, guaranteeing that it will be called exactly
00289 // once per process.                                                       
00290 //                                                                         
00291 // <Pthread function declarations>=                                        
00292 __BEGIN_DECLS
00293 typedef void (*GUSIPThreadOnceProc)(void);
00294 __END_DECLS
00295 
00296 int pthread_once(pthread_once_t * once_block, GUSIPThreadOnceProc proc);
00297 __END_DECLS
00298 
00299 #endif /* _PTHREAD_H_ */