(file) Return to Thread.h CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 martin 1.66 //%LICENSE////////////////////////////////////////////////////////////////
  2 martin 1.67 //
  3 martin 1.66 // Licensed to The Open Group (TOG) under one or more contributor license
  4             // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
  5             // this work for additional information regarding copyright ownership.
  6             // Each contributor licenses this file to you under the OpenPegasus Open
  7             // Source License; you may not use this file except in compliance with the
  8             // License.
  9 martin 1.67 //
 10 martin 1.66 // Permission is hereby granted, free of charge, to any person obtaining a
 11             // copy of this software and associated documentation files (the "Software"),
 12             // to deal in the Software without restriction, including without limitation
 13             // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 14             // and/or sell copies of the Software, and to permit persons to whom the
 15             // Software is furnished to do so, subject to the following conditions:
 16 martin 1.67 //
 17 martin 1.66 // The above copyright notice and this permission notice shall be included
 18             // in all copies or substantial portions of the Software.
 19 martin 1.67 //
 20 martin 1.66 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 21 martin 1.67 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 22 martin 1.66 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 23             // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 24             // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 25             // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 26             // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 27 martin 1.67 //
 28 martin 1.66 //////////////////////////////////////////////////////////////////////////
 29 mike   1.2  //
 30             //%/////////////////////////////////////////////////////////////////////////////
 31             
 32             #ifndef Pegasus_Thread_h
 33             #define Pegasus_Thread_h
 34 kumpf  1.26 
 35             #include <cstring>
 36 mike   1.2  #include <Pegasus/Common/Config.h>
 37 mike   1.58 #include <Pegasus/Common/AtomicInt.h>
 38 kumpf  1.23 #include <Pegasus/Common/InternalException.h>
 39 kumpf  1.54 #include <Pegasus/Common/AcceptLanguageList.h>
 40 kumpf  1.22 #include <Pegasus/Common/Linkage.h>
 41 a.arora 1.37 #include <Pegasus/Common/AutoPtr.h>
 42 mike    1.56 #include <Pegasus/Common/List.h>
 43 mike    1.58 #include <Pegasus/Common/Mutex.h>
 44              #include <Pegasus/Common/Semaphore.h>
 45              #include <Pegasus/Common/TSDKey.h>
 46              #include <Pegasus/Common/Threads.h>
 47 mike    1.2  
 48 mike    1.58 #if defined(PEGASUS_HAVE_PTHREADS)
 49              # include <signal.h>
 50              #endif
 51              
 52 kumpf   1.59 PEGASUS_NAMESPACE_BEGIN
 53 mike    1.2  
 54 mike    1.56 class PEGASUS_COMMON_LINKAGE cleanup_handler : public Linkable
 55 mike    1.2  {
 56 mike    1.58 public:
 57                  cleanup_handler(void (*routine) (void *), void *arg):_routine(routine),
 58                      _arg(arg)
 59                  {
 60                  }
 61                  ~cleanup_handler()
 62                  {;
 63                  }
 64              
 65              private:
 66              
 67                  void execute()
 68                  {
 69                      _routine(_arg);
 70                  }
 71              
 72 kumpf   1.59     cleanup_handler();
 73              
 74 mike    1.58     void (*_routine)(void*);
 75                  void *_arg;
 76 mike    1.2  
 77 mike    1.58     friend class Thread;
 78 mike    1.2  };
 79              
 80              ///////////////////////////////////////////////////////////////////////////////
 81              
 82 mike    1.64 enum TSD_Key
 83 mike    1.58 {
 84 mike    1.64     TSD_ACCEPT_LANGUAGES,
 85                  TSD_SLEEP_SEM,
 86                  TSD_LAST_ACTIVITY_TIME,
 87                  TSD_WORK_FUNC,
 88                  TSD_WORK_PARM,
 89                  TSD_BLOCKING_SEM,
 90                  TSD_CIMOM_HANDLE_CONTENT_LANGUAGES,
 91                  TSD_RESERVED_1,
 92                  TSD_RESERVED_2,
 93                  TSD_RESERVED_3,
 94                  TSD_RESERVED_4,
 95                  TSD_RESERVED_5,
 96                  TSD_RESERVED_6,
 97                  TSD_RESERVED_7,
 98                  TSD_RESERVED_8,
 99                  // Add new TSD keys before this line.
100 kumpf   1.65     TSD_COUNT
101 mike    1.64 };
102              
103              class thread_data
104              {
105                  /**
106                   * This class is NOT build thread-safe.
107                   * The Caller(user) of this class has to ensure there is no collision
108                   * taking place.
109 kumpf   1.68      *
110 mike    1.64      * There is no mechanism in place to protect threads from manipulating
111                   * the same thread-specific storage at one time.
112                   * Make sure the possibility for a parallel access to the same
113                   * threads-specific data from multiple threads cannot arise.
114 kumpf   1.68      *
115 mike    1.64      * In OpenPegasus this class is used in the ThreadPool
116                   *        - on initialisation and creation of threads owned by ThreadPool
117                   *        - on threads that are idle inside the ThreadPool
118                   *        - on the ThreadPools main thread (the thread which the ThreadPool
119                   *          runs in)
120 kumpf   1.68      * In OpenPegasus this class is used in the
121 mike    1.64      * ClientCIMOMHandleRep and InternalCIMOMHandleRep
122                   *        - on the current active Thread which belongs to that CIMOMHandle
123 kumpf   1.68      *
124 mike    1.64      */
125 mike    1.58 public:
126              
127 mike    1.64     static void default_delete(void *data)
128                  {
129                      if (data)
130                          ::operator  delete(data);
131                  }
132 mike    1.58 
133 mike    1.64     thread_data(TSD_Key key) : _delete_func(0), _data(0), _size(0), _key(key)
134 mike    1.58     {
135                  }
136 mike    1.2  
137 mike    1.64     thread_data(TSD_Key key, size_t size) :
138                      _delete_func(default_delete), _size(size), _key(key)
139 mike    1.58     {
140 mike    1.64         _data = ::operator  new(_size);
141 mike    1.58     }
142 mike    1.2  
143 mike    1.64     thread_data(TSD_Key key, size_t size, void* data)
144                      : _delete_func(default_delete), _size(size), _key(key)
145 mike    1.58     {
146 mike    1.64         _data = ::operator  new(_size);
147 mike    1.58         memcpy(_data, data, size);
148                  }
149 kumpf   1.48 
150 mike    1.58     ~thread_data()
151                  {
152 mike    1.64         if (_data && _delete_func)
153                          (*_delete_func)(_data);
154 mike    1.58     }
155 mike    1.2  
156 mike    1.58     /**
157                   * This function is used to put data in thread space.
158                   *
159                   * Be aware that there is NOTHING in place to stop
160                   * other users of the thread to remove this data.
161                   * Or change the data.
162                   *
163                   * You, the developer has to make sure that there are
164                   * no situations in which this can arise (ie, have a
165                   * lock for the function which manipulates the TSD.
166                   *
167                   * @exception NullPointer
168                  */
169 mike    1.64     void put_data(void (*del)(void *), size_t size, void* data)
170 mike    1.58     {
171 mike    1.64         if (_data && _delete_func)
172                          (*_delete_func)(_data);
173 mike    1.58 
174                      _delete_func = del;
175                      _data = data;
176                      _size = size;
177                  }
178 mike    1.2  
179 mike    1.58     size_t get_size()
180                  {
181                      return _size;
182                  }
183 mike    1.2  
184 mike    1.64     void* get_data()
185                  {
186                      return _data;
187                  }
188              
189 kumpf   1.59     /**
190                      This function is used to retrieve data from the
191                      TSD, the thread specific data.
192              
193                      Be aware that there is NOTHING in place to stop
194                      other users of the thread to change the data you
195                      get from this function.
196              
197                      You, the developer has to make sure that there are
198                      no situations in which this can arise (ie, have a
199                      lock for the function which manipulates the TSD.
200                   */
201                  void get_data(void** data, size_t* size)
202 mike    1.58     {
203 mike    1.64         if (data == 0 || size == 0)
204 kumpf   1.48             throw NullPointer();
205              
206 mike    1.58         *data = _data;
207                      *size = _size;
208                  }
209              
210                  // @exception NullPointer
211 kumpf   1.59     void copy_data(void** buf, size_t* size)
212 mike    1.58     {
213 mike    1.64         if ((buf == 0) || (size == 0))
214 david.dillard 1.50             throw NullPointer();
215 mike          1.64 
216                            *buf = ::operator new(_size);
217 mike          1.58         *size = _size;
218                            memcpy(*buf, _data, _size);
219                        }
220 mike          1.2  
221 mike          1.58 
222 mike          1.64 private:
223 mike          1.58 
224 mike          1.64     thread_data();
225                        thread_data(const thread_data& x);
226                        thread_data& operator=(const thread_data& x);
227 mike          1.58 
228 mike          1.64     void (*_delete_func)(void*);
229 kumpf         1.59     void* _data;
230 mike          1.58     size_t _size;
231 mike          1.64     TSD_Key _key;
232 mike          1.2  };
233                    
234                    
235 mike          1.58 enum ThreadStatus
236                    {
237                        PEGASUS_THREAD_OK = 1,      /* No problems */
238                        PEGASUS_THREAD_INSUFFICIENT_RESOURCES,      /* Can't allocate a thread.
239                                                                       Not enough memory. Try
240                                                                       again later */
241 kumpf         1.59     PEGASUS_THREAD_SETUP_FAILURE,       /* Could not allocate into the thread
242 mike          1.58                                            specific data storage. */
243                        PEGASUS_THREAD_UNAVAILABLE  /* Service is being destroyed and no new
244                                                       threads can be provided. */
245 konrad.r      1.53 };
246                    
247 mike          1.2  ///////////////////////////////////////////////////////////////////////////
248                    
249 kumpf         1.59 class PEGASUS_COMMON_LINKAGE Thread : public Linkable
250 mike          1.2  {
251 kumpf         1.59 public:
252 mike          1.2  
253 kumpf         1.59     Thread(
254                            ThreadReturnType(PEGASUS_THREAD_CDECL* start) (void*),
255                            void* parameter,
256                            Boolean detached);
257 mike          1.2  
258 mike          1.58      ~Thread();
259 mike          1.2  
260 mike          1.58       /** Start the thread.
261 kumpf         1.59           @return PEGASUS_THREAD_OK if the thread is started successfully,
262                              PEGASUS_THREAD_INSUFFICIENT_RESOURCES if the resources necessary
263                              to start the thread are not currently available.
264                              PEGASUS_THREAD_SETUP_FAILURE if the thread could not
265 mike          1.58           be create properly - check the 'errno' value for specific operating
266                              system return code.
267 kumpf         1.36        */
268 mike          1.58     ThreadStatus run();
269 mike          1.2  
270 mike          1.58     // get the user parameter
271 mike          1.64     void *get_parm()
272 mike          1.58     {
273                            return _thread_parm;
274                        }
275 mike          1.2  
276 mike          1.58     // cancellation must be deferred (not asynchronous)
277                        // for user-level threads the thread itself can decide
278                        // when it should die.
279                        void cancel();
280                    
281                        // for user-level threads - put the calling thread
282                        // to sleep and jump to the thread scheduler.
283                        // platforms with preemptive scheduling and native threads
284                        // can define this to be a no-op.
285                        // platforms without preemptive scheduling like NetWare
286                        // or gnu portable threads will have an existing
287                        // routine that can be mapped to this method
288 mike          1.2  
289 mike          1.58     void thread_switch();
290 mike          1.2  
291 mike          1.58     static void sleep(Uint32 msec);
292 mike          1.2  
293 mike          1.58     // block the calling thread until this thread terminates
294                        void join();
295                    
296                        // thread routine needs to call this function when
297                        // it is ready to exit
298                        void exit_self(ThreadReturnType return_code);
299                    
300                        // stack of functions to be called when thread terminates
301                        // will be called last in first out (LIFO)
302 kumpf         1.59     void cleanup_push(void (*routine) (void *), void* parm);
303 mike          1.58 
304                        void cleanup_pop(Boolean execute = true);
305                    
306                        // get the buffer associated with the key
307                        // NOTE: this call leaves the tsd LOCKED !!!!
308 mike          1.64     void* reference_tsd(TSD_Key key)
309 mike          1.58     {
310 mike          1.64         if (_tsd[key])
311                                return _tsd[key]->get_data();
312                             else
313                                return 0;
314 mike          1.58     }
315 mike          1.2  
316 mike          1.58     // release the lock held on the tsd
317                        // NOTE: assumes a corresponding and prior call to reference_tsd() !!!
318 mike          1.64     void dereference_tsd()
319 mike          1.58     {
320                        }
321 kumpf         1.48 
322 mike          1.58     // delete the tsd associated with the key
323 mike          1.64     void delete_tsd(TSD_Key key)
324 kumpf         1.48     {
325 mike          1.64         thread_data* tsd;
326                    
327                            tsd = _tsd[key];
328                            _tsd[key] = 0;
329                    
330                            if (tsd)
331                                delete tsd;
332 kumpf         1.48     }
333                    
334 mike          1.64     void empty_tsd()
335 kumpf         1.48     {
336 mike          1.64         thread_data* data[TSD_COUNT];
337                    
338                            memcpy(data, _tsd, sizeof(_tsd));
339                            memset(_tsd, 0, sizeof(_tsd));
340                    
341                            for (size_t i = 0; i < TSD_COUNT; i++)
342                            {
343                                if (data[i])
344                                    delete data[i];
345                            }
346 kumpf         1.48     }
347                    
348 mike          1.58     // create or re-initialize tsd associated with the key
349                        // if the tsd already exists, delete the existing buffer
350 kumpf         1.59     void put_tsd(
351 mike          1.64         TSD_Key key,
352                            void (*delete_func)(void*),
353 kumpf         1.59         Uint32 size,
354                            void* value)
355 kumpf         1.48     {
356 mike          1.64         thread_data* tsd = new thread_data(key);
357                            tsd->put_data(delete_func, size, value);
358                    
359                            thread_data* old;
360                    
361                            old = _tsd[key];
362                            _tsd[key] = tsd;
363                    
364                            if (old)
365                                delete old;
366 kumpf         1.48     }
367 kumpf         1.59 
368 mike          1.64     ThreadReturnType get_exit()
369 kumpf         1.48     {
370 mike          1.58         return _exit_code;
371 kumpf         1.48     }
372 mike          1.64 
373                        ThreadType self()
374 kumpf         1.48     {
375 mike          1.58         return Threads::self();
376 kumpf         1.48     }
377                    
378 mike          1.58     ThreadHandle getThreadHandle()
379 kumpf         1.48     {
380 mike          1.58         return _handle;
381 kumpf         1.48     }
382                    
383 venkat.puvvada 1.68.2.1     Boolean isDetached()
384                             {
385                                 return _is_detached;
386                             }
387                         
388 mike           1.58         void detach();
389                         
390 kumpf          1.59         //
391 mike           1.58         // Gets the Thread object associated with the caller's thread.
392                             // Note: this may return NULL if no Thread object is associated
393                             // with the caller's thread.
394 kumpf          1.59         //
395                             static Thread *getCurrent();
396 mike           1.58     
397 kumpf          1.59         //
398 mike           1.58         // Sets the Thread object associated with the caller's thread.
399                             // Note: the Thread object must be placed on the heap.
400 kumpf          1.59         //
401                             static void setCurrent(Thread* thrd);
402 mike           1.58     
403 kumpf          1.59         //
404 mike           1.58         // Gets the AcceptLanguageList object associated with the caller's
405                             // Thread.
406                             // Note: this may return NULL if no Thread object, or no
407                             // AcceptLanguageList object, is associated with the caller's thread.
408 kumpf          1.59         //
409                             static AcceptLanguageList* getLanguages();
410 mike           1.58     
411 kumpf          1.59         //
412 mike           1.58         // Sets the AcceptLanguageList object associated with the caller's
413                             // Thread.
414                             // Note: a Thread object must have been previously associated with
415                             // the caller's thread.
416 kumpf          1.59         //
417 kumpf          1.60         static void setLanguages(const AcceptLanguageList& langs);
418 mike           1.58     
419 kumpf          1.59         //
420 mike           1.58         // Removes the AcceptLanguageList object associated with the caller's
421                             // Thread.
422 kumpf          1.59         //
423                             static void clearLanguages();
424 kumpf          1.48     
425 kumpf          1.59     private:
426 mike           1.58         Thread();
427 mike           1.2      
428 kumpf          1.59         static Sint8 initializeKey();
429 mike           1.2      
430 mike           1.58         ThreadHandle _handle;
431                             Boolean _is_detached;
432                             Boolean _cancelled;
433                         
434                             // always pass this * as the void * parameter to the thread
435                             // store the user parameter in _thread_parm
436                         
437 kumpf          1.59         ThreadReturnType(PEGASUS_THREAD_CDECL* _start) (void *);
438                             List<cleanup_handler, Mutex> _cleanup;
439 mike           1.64         thread_data* _tsd[TSD_COUNT];
440 mike           1.58     
441 kumpf          1.59         void* _thread_parm;
442 mike           1.58         ThreadReturnType _exit_code;
443                             static Boolean _signals_blocked;
444 kumpf          1.59         static TSDKeyType _platform_thread_key;
445                             static Boolean _key_initialized;
446                             static Boolean _key_error;
447 mike           1.58     };
448 mike           1.2      
449                         PEGASUS_NAMESPACE_END
450                         
451                         #endif // Pegasus_Thread_h

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2