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

Diff for /pegasus/src/Pegasus/Common/Thread.h between version 1.57.2.4 and 1.69

version 1.57.2.4, 2006/07/29 01:08:49 version 1.69, 2009/08/13 13:13:07
Line 1 
Line 1 
 //%2006////////////////////////////////////////////////////////////////////////  //%LICENSE////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development  // Licensed to The Open Group (TOG) under one or more contributor license
 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.  // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;  // this work for additional information regarding copyright ownership.
 // IBM Corp.; EMC Corporation, The Open Group.  // Each contributor licenses this file to you under the OpenPegasus Open
 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;  // Source License; you may not use this file except in compliance with the
 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.  // License.
 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;  //
 // EMC Corporation; VERITAS Software Corporation; The Open Group.  // Permission is hereby granted, free of charge, to any person obtaining a
 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;  // copy of this software and associated documentation files (the "Software"),
 // EMC Corporation; Symantec Corporation; The Open Group.  // to deal in the Software without restriction, including without limitation
 //  // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 // Permission is hereby granted, free of charge, to any person obtaining a copy  // and/or sell copies of the Software, and to permit persons to whom the
 // of this software and associated documentation files (the "Software"), to  // Software is furnished to do so, subject to the following conditions:
 // deal in the Software without restriction, including without limitation the  //
 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  // The above copyright notice and this permission notice shall be included
 // sell copies of the Software, and to permit persons to whom the Software is  // in all copies or substantial portions of the Software.
 // furnished to do so, subject to the following conditions:  //
 //  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN  // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT  // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR  // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT  // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN  // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION  //
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  //////////////////////////////////////////////////////////////////////////
 //  
 //==============================================================================  
 //  
 // Author: Mike Day (mdday@us.ibm.com)  
 //  
 // Modified By: Markus Mueller  
 //              Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)  
 //              Amit K Arora, IBM (amita@in.ibm.com) for PEP#101  
 //              David Dillard, VERITAS Software Corp.  
 //                  (david.dillard@veritas.com)  
 //              Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com)  
 //              Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#2393  
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
Line 91 
Line 79 
  
 /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
  
 class PEGASUS_COMMON_LINKAGE thread_data : public Linkable  enum TSD_Key
   {
       TSD_ACCEPT_LANGUAGES,
       TSD_SLEEP_SEM,
       TSD_LAST_ACTIVITY_TIME,
       TSD_WORK_FUNC,
       TSD_WORK_PARM,
       TSD_BLOCKING_SEM,
       TSD_CIMOM_HANDLE_CONTENT_LANGUAGES,
       TSD_RESERVED_1,
       TSD_RESERVED_2,
       TSD_RESERVED_3,
       TSD_RESERVED_4,
       TSD_RESERVED_5,
       TSD_RESERVED_6,
       TSD_RESERVED_7,
       TSD_RESERVED_8,
       // Add new TSD keys before this line.
       TSD_COUNT
   };
   
   class thread_data
 { {
       /**
        * This class is NOT build thread-safe.
        * The Caller(user) of this class has to ensure there is no collision
        * taking place.
        *
        * There is no mechanism in place to protect threads from manipulating
        * the same thread-specific storage at one time.
        * Make sure the possibility for a parallel access to the same
        * threads-specific data from multiple threads cannot arise.
        *
        * In OpenPegasus this class is used in the ThreadPool
        *        - on initialisation and creation of threads owned by ThreadPool
        *        - on threads that are idle inside the ThreadPool
        *        - on the ThreadPools main thread (the thread which the ThreadPool
        *          runs in)
        * In OpenPegasus this class is used in the
        * ClientCIMOMHandleRep and InternalCIMOMHandleRep
        *        - on the current active Thread which belongs to that CIMOMHandle
        *
        */
 public: public:
  
     static void default_delete(void *data);      static void default_delete(void *data)
       {
           if (data)
               ::operator  delete(data);
       }
  
     thread_data(const char *key) : _delete_func(NULL), _data(NULL), _size(0)      thread_data(TSD_Key key) : _delete_func(0), _data(0), _size(0), _key(key)
     {     {
         PEGASUS_ASSERT(key != NULL);  
         size_t keysize = strlen(key);  
         _key.reset(new char[keysize + 1]);  
         memcpy(_key.get(), key, keysize);  
         _key.get()[keysize] = 0x00;  
     }     }
  
     thread_data(const char *key, size_t size) :      thread_data(TSD_Key key, size_t size) :
         _delete_func(default_delete), _size(size)          _delete_func(default_delete), _size(size), _key(key)
     {     {
         PEGASUS_ASSERT(key != NULL);  
         size_t keysize = strlen(key);  
         _key.reset(new char[keysize + 1]);  
         memcpy(_key.get(), key, keysize);  
         _key.get()[keysize] = 0x00;  
         _data =::operator  new(_size);         _data =::operator  new(_size);
     }     }
  
     thread_data(const char *key, size_t size, void *data) :      thread_data(TSD_Key key, size_t size, void* data)
         _delete_func(default_delete), _size(size)          : _delete_func(default_delete), _size(size), _key(key)
     {     {
         PEGASUS_ASSERT(key != NULL);  
         PEGASUS_ASSERT(data != NULL);  
         size_t keysize = strlen(key);  
   
         _key.reset(new char[keysize + 1]);  
         memcpy(_key.get(), key, keysize);  
         _key.get()[keysize] = 0x00;  
         _data =::operator  new(_size);         _data =::operator  new(_size);
         memcpy(_data, data, size);         memcpy(_data, data, size);
     }     }
  
     ~thread_data()     ~thread_data()
     {     {
         if (_data != NULL)          if (_data && _delete_func)
             if (_delete_func != NULL)              (*_delete_func)(_data);
             {  
                 _delete_func(_data);  
             }  
     }     }
  
     /**     /**
Line 155 
Line 168 
     */     */
     void put_data(void (*del) (void *), size_t size, void *data)     void put_data(void (*del) (void *), size_t size, void *data)
     {     {
         if (_data != NULL)          if (_data && _delete_func)
             if (_delete_func != NULL)              (*_delete_func)(_data);
                 _delete_func(_data);  
  
         _delete_func = del;         _delete_func = del;
         _data = data;         _data = data;
         _size = size;         _size = size;
         return;  
     }     }
  
     size_t get_size()     size_t get_size()
Line 170 
Line 181 
         return _size;         return _size;
     }     }
  
       void* get_data()
       {
           return _data;
       }
   
       /**       /**
        * This function is used to retrieve data from the          This function is used to retrieve data from the
        * TSD, the thread specific data.          TSD, the thread specific data.
        *  
        * Be aware that there is NOTHING in place to stop          Be aware that there is NOTHING in place to stop
        * other users of the thread to change the data you          other users of the thread to change the data you
        * get from this function.          get from this function.
        *  
        * You, the developer has to make sure that there are          You, the developer has to make sure that there are
        * no situations in which this can arise (ie, have a          no situations in which this can arise (ie, have a
        * lock for the function which manipulates the TSD.          lock for the function which manipulates the TSD.
        */        */
     void get_data(void **data, size_t * size)     void get_data(void **data, size_t * size)
     {     {
         if (data == NULL || size == NULL)          if (data == 0 || size == 0)
             throw NullPointer();             throw NullPointer();
  
         *data = _data;         *data = _data;
         *size = _size;         *size = _size;
         return;  
   
     }     }
  
     // @exception NullPointer     // @exception NullPointer
     void copy_data(void **buf, size_t * size)     void copy_data(void **buf, size_t * size)
     {     {
         if ((buf == NULL) || (size == NULL))          if ((buf == 0) || (size == 0))
             throw NullPointer();             throw NullPointer();
   
         *buf =::operator  new(_size);         *buf =::operator  new(_size);
         *size = _size;         *size = _size;
         memcpy(*buf, _data, _size);         memcpy(*buf, _data, _size);
         return;  
     }  
   
     inline Boolean operator==(const void *key) const  
     {  
         if (!strcmp(_key.get(), reinterpret_cast < const char *>(key)))  
               return (true);  
           return (false);  
     }     }
  
     inline Boolean operator==(const thread_data & b) const  
     {  
         return (operator==(b._key.get()));  
     }  
   
     static bool equal(const thread_data * node, const void *key)  
     {  
         return ((thread_data *) node)->operator==(key);  
     }  
  
   private:   private:
     void (*_delete_func) (void *data);  
     thread_data();     thread_data();
       thread_data(const thread_data& x);
       thread_data& operator=(const thread_data& x);
   
       void (*_delete_func)(void*);
     void *_data;     void *_data;
     size_t _size;     size_t _size;
     AutoArrayPtr < char >_key;      TSD_Key _key;
   
     friend class Thread;  
 }; };
  
  
Line 250 
Line 250 
 { {
   public:   public:
  
     Thread(ThreadReturnType(PEGASUS_THREAD_CDECL * start) (void *),      Thread(
            void *parameter, Boolean detached);          ThreadReturnType(PEGASUS_THREAD_CDECL* start) (void*),
           void* parameter,
           Boolean detached);
  
      ~Thread();      ~Thread();
  
Line 266 
Line 268 
     ThreadStatus run();     ThreadStatus run();
  
     // get the user parameter     // get the user parameter
     inline void *get_parm()      void *get_parm()
     {     {
         return _thread_parm;         return _thread_parm;
     }     }
Line 276 
Line 278 
     // when it should die.     // when it should die.
     void cancel();     void cancel();
  
     // cancel if there is a pending cancellation request  
     void test_cancel();  
   
     Boolean is_cancelled();  
   
     // for user-level threads - put the calling thread     // for user-level threads - put the calling thread
     // to sleep and jump to the thread scheduler.     // to sleep and jump to the thread scheduler.
     // platforms with preemptive scheduling and native threads     // platforms with preemptive scheduling and native threads
Line 291 
Line 288 
  
     void thread_switch();     void thread_switch();
  
 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)  
     // suspend this thread  
     void suspend();  
   
     // resume this thread  
     void resume();  
 #endif  
   
     static void sleep(Uint32 msec);     static void sleep(Uint32 msec);
  
     // block the calling thread until this thread terminates     // block the calling thread until this thread terminates
     void join();     void join();
     void thread_init();  
  
     // thread routine needs to call this function when     // thread routine needs to call this function when
     // it is ready to exit     // it is ready to exit
Line 311 
Line 299 
  
     // stack of functions to be called when thread terminates     // stack of functions to be called when thread terminates
     // will be called last in first out (LIFO)     // will be called last in first out (LIFO)
     // @exception IPCException  
     void cleanup_push(void (*routine) (void *), void *parm);     void cleanup_push(void (*routine) (void *), void *parm);
  
     // @exception IPCException  
     void cleanup_pop(Boolean execute = true);     void cleanup_pop(Boolean execute = true);
  
     // create and initialize a tsd  
     // @exception IPCException  
     inline void create_tsd(const char *key, int size, void *buffer)  
     {  
         AutoPtr < thread_data > tsd(new thread_data(key, size, buffer));  
         _tsd.insert_front(tsd.get());  
         tsd.release();  
     }  
   
     // get the buffer associated with the key     // get the buffer associated with the key
     // NOTE: this call leaves the tsd LOCKED !!!!     // NOTE: this call leaves the tsd LOCKED !!!!
     // @exception IPCException      void* reference_tsd(TSD_Key key)
     inline void *reference_tsd(const char *key)  
     {     {
         _tsd.lock();          if (_tsd[key])
         thread_data *tsd = _tsd.find(thread_data::equal, key);              return _tsd[key]->get_data();
         if (tsd != NULL)  
             return ((void *) (tsd->_data));  
         else         else
             return (NULL);              return 0;
     }     }
  
     // @exception IPCException  
     inline void *try_reference_tsd(const char *key)  
     {  
         _tsd.try_lock();  
         thread_data *tsd = _tsd.find(thread_data::equal, key);  
         if (tsd != NULL)  
             return ((void *) (tsd->_data));  
         else  
             return (NULL);  
     }  
   
   
     // release the lock held on the tsd     // release the lock held on the tsd
     // NOTE: assumes a corresponding and prior call to reference_tsd() !!!     // NOTE: assumes a corresponding and prior call to reference_tsd() !!!
     // @exception IPCException      void dereference_tsd()
     inline void dereference_tsd()  
     {     {
         _tsd.unlock();  
     }     }
  
     // delete the tsd associated with the key     // delete the tsd associated with the key
     // @exception IPCException      void delete_tsd(TSD_Key key)
     inline void delete_tsd(const char *key)  
     {     {
         AutoPtr < thread_data > tsd(_tsd.remove(thread_data::equal, key));          thread_data* tsd;
   
           tsd = _tsd[key];
           _tsd[key] = 0;
   
           if (tsd)
               delete tsd;
     }     }
  
     // @exception IPCException      void empty_tsd()
     inline void empty_tsd()  
     {     {
         _tsd.clear();          thread_data* data[TSD_COUNT];
   
           memcpy(data, _tsd, sizeof(_tsd));
           memset(_tsd, 0, sizeof(_tsd));
   
           for (size_t i = 0; i < TSD_COUNT; i++)
           {
               if (data[i])
                   delete data[i];
           }
     }     }
  
     // create or re-initialize tsd associated with the key     // create or re-initialize tsd associated with the key
     // if the tsd already exists, delete the existing buffer     // if the tsd already exists, delete the existing buffer
     // @exception IPCException      void put_tsd(
     void put_tsd(const char *key, void (*delete_func) (void *), Uint32 size,          TSD_Key key,
           void (*delete_func)(void*),
           Uint32 size,
                  void *value)                  void *value)
     {     {
         PEGASUS_ASSERT(key != NULL);          thread_data* tsd = new thread_data(key);
         AutoPtr < thread_data > tsd;          tsd->put_data(delete_func, size, value);
         tsd.reset(_tsd.remove(thread_data::equal, key));        // may throw  
                                                                 // an IPC          thread_data* old;
                                                                 // exception  
         tsd.reset();          old = _tsd[key];
         AutoPtr < thread_data > ntsd(new thread_data(key));          _tsd[key] = tsd;
         ntsd->put_data(delete_func, size, value);  
         try          if (old)
         {              delete old;
             _tsd.insert_front(ntsd.get());  
         }  
         catch(IPCException & e)  
         {  
             e = e;  
             throw;  
         }  
         ntsd.release();  
     }     }
     inline ThreadReturnType get_exit()  
       ThreadReturnType get_exit()
     {     {
         return _exit_code;         return _exit_code;
     }     }
     inline ThreadType self()  
       ThreadType self()
     {     {
         return Threads::self();         return Threads::self();
     }     }
Line 411 
Line 380 
         return _handle;         return _handle;
     }     }
  
       Boolean isDetached()
       {
           return _is_detached;
       }
   
     void detach();     void detach();
  
     //     //
Line 418 
Line 392 
     // Note: this may return NULL if no Thread object is associated     // Note: this may return NULL if no Thread object is associated
     // with the caller's thread.     // with the caller's thread.
     //     //
     static Thread *getCurrent();        // l10n      static Thread *getCurrent();
  
     //     //
     // Sets the Thread object associated with the caller's thread.     // Sets the Thread object associated with the caller's thread.
     // Note: the Thread object must be placed on the heap.     // Note: the Thread object must be placed on the heap.
     //     //
     static void setCurrent(Thread * thrd);      // l10n      static void setCurrent(Thread* thrd);
  
     //     //
     // Gets the AcceptLanguageList object associated with the caller's     // Gets the AcceptLanguageList object associated with the caller's
Line 432 
Line 406 
     // Note: this may return NULL if no Thread object, or no     // Note: this may return NULL if no Thread object, or no
     // AcceptLanguageList object, is associated with the caller's thread.     // AcceptLanguageList object, is associated with the caller's thread.
     //     //
     static AcceptLanguageList *getLanguages();  // l10n      static AcceptLanguageList* getLanguages();
  
     //     //
     // Sets the AcceptLanguageList object associated with the caller's     // Sets the AcceptLanguageList object associated with the caller's
     // Thread.     // Thread.
     // Note: a Thread object must have been previously associated with     // Note: a Thread object must have been previously associated with
     // the caller's thread.     // the caller's thread.
     // Note: the AcceptLanguageList object must be placed on the heap.  
     //     //
     static void setLanguages(AcceptLanguageList * langs);       // l10n      static void setLanguages(const AcceptLanguageList& langs);
  
     //     //
     // Removes the AcceptLanguageList object associated with the caller's     // Removes the AcceptLanguageList object associated with the caller's
     // Thread.     // Thread.
     //     //
     static void clearLanguages();       // l10n      static void clearLanguages();
  
   private:   private:
     Thread();     Thread();
  
     static Sint8 initializeKey();       // l10n      static Sint8 initializeKey();
  
     // @exception IPCException  
     inline void create_tsd(const char *key)  
     {  
         AutoPtr < thread_data > tsd(new thread_data(key));  
         _tsd.insert_front(tsd.get());  
         tsd.release();  
     }  
     ThreadHandle _handle;     ThreadHandle _handle;
     Boolean _is_detached;     Boolean _is_detached;
     Boolean _cancel_enabled;  
     Boolean _cancelled;     Boolean _cancelled;
  
     // always pass this * as the void * parameter to the thread     // always pass this * as the void * parameter to the thread
Line 471 
Line 436 
  
     ThreadReturnType(PEGASUS_THREAD_CDECL * _start) (void *);     ThreadReturnType(PEGASUS_THREAD_CDECL * _start) (void *);
     List < cleanup_handler, Mutex > _cleanup;     List < cleanup_handler, Mutex > _cleanup;
     List < thread_data, Mutex > _tsd;      thread_data* _tsd[TSD_COUNT];
  
     void *_thread_parm;     void *_thread_parm;
     ThreadReturnType _exit_code;     ThreadReturnType _exit_code;
     static Boolean _signals_blocked;     static Boolean _signals_blocked;
     static TSDKeyType _platform_thread_key;     // l10n      static TSDKeyType _platform_thread_key;
     static Boolean _key_initialized;    // l10n      static Boolean _key_initialized;
     static Boolean _key_error;  // l10n      static Boolean _key_error;
 };  
   
   
 class PEGASUS_COMMON_LINKAGE ThreadPool  
 {  
   public:  
   
     /**  
         Constructs a new ThreadPool object.  
         @param initialSize The number of threads that are initially added to  
             the thread pool.  
         @param key A name for this thread pool that can be used to determine  
             equality of two thread pool objects.  Only the first 16 characters  
             of this value are used.  
         @param minThreads The minimum number of threads that should be  
             contained in this thread pool at any given time.  
         @param maxThreads The maximum number of threads that should be  
             contained in this thread pool at any given time.  
         @param deallocateWait The minimum time that a thread should be idle  
             before it is removed from the pool and cleaned up.  
      */  
     ThreadPool(Sint16 initialSize,  
                const char *key,  
                Sint16 minThreads,  
                Sint16 maxThreads, struct timeval &deallocateWait);  
   
     /**  
         Destructs the ThreadPool object.  
      */  
      ~ThreadPool();  
   
     /**  
         Allocate and start a thread to do a unit of work.  
         @param parm A generic parameter to pass to the thread  
         @param work A pointer to the function that is to be executed by  
                     the thread  
         @param blocking A pointer to an optional semaphore which, if  
                         specified, is signaled after the thread finishes  
                         executing the work function  
         @return PEGASUS_THREAD_OK if the thread is started successfully,  
                 PEGASUS_THREAD_INSUFFICIENT_RESOURCES  if the  
                 resources necessary to start the thread are not currently  
                 available.  PEGASUS_THREAD_SETUP_FAILURE if the thread  
                 could not be setup properly. PEGASUS_THREAD_UNAVAILABLE  
                 if this service is shutting down and no more threads can  
                 be allocated.  
         @exception IPCException  
      */  
     ThreadStatus allocate_and_awaken(void *parm,  
                                      ThreadReturnType(PEGASUS_THREAD_CDECL *  
                                                       work) (void *),  
                                      Semaphore * blocking = 0);  
   
     /**  
         Cleans up idle threads if they have been running longer than the  
         deallocate_wait configuration and more than the configured  
         minimum number of threads is running.  
         @return The number of threads that were cleaned up.  
         @exception IPCException  
      */  
     Uint32 cleanupIdleThreads();  
   
     void get_key(Sint8 * buf, int bufsize);  
   
     inline void setMinThreads(Sint16 min)  
     {  
         _minThreads = min;  
     }  
   
     inline Sint16 getMinThreads() const  
     {  
         return _minThreads;  
     }  
   
     inline void setMaxThreads(Sint16 max)  
     {  
         _maxThreads = max;  
     }  
   
     inline Sint16 getMaxThreads() const  
     {  
         return _maxThreads;  
     }  
   
     inline Uint32 runningCount()  
     {  
         return _runningThreads.size();  
     }  
   
     inline Uint32 idleCount()  
     {  
         return _idleThreads.size();  
     }  
   
   private:  
   
     ThreadPool();               // Unimplemented  
     ThreadPool(const ThreadPool &);     // Unimplemented  
     ThreadPool & operator=(const ThreadPool &); // Unimplemented  
   
     static ThreadReturnType PEGASUS_THREAD_CDECL _loop(void *);  
   
     static Boolean _timeIntervalExpired(struct timeval *start,  
                                         struct timeval *interval);  
   
     static void _deleteSemaphore(void *p);  
   
     void _cleanupThread(Thread * thread);  
     Thread *_initializeThread();  
     void _addToIdleThreadsQueue(Thread * th);  
   
     Sint16 _maxThreads;  
     Sint16 _minThreads;  
     AtomicInt _currentThreads;  
     struct timeval _deallocateWait;  
     char _key[17];  
     List < Thread, Mutex > _idleThreads;  
     List < Thread, Mutex > _runningThreads;  
     AtomicInt _dying;  
 };  
   
 //==============================================================================  
 //  
 // POSIX Threads Implementation:  
 //  
 //==============================================================================  
   
 #if defined(PEGASUS_HAVE_PTHREADS)  
   
 struct StartWrapperArg  
 {  
     void *(PEGASUS_THREAD_CDECL * start) (void *);  
     void *arg;  
 }; };
  
 extern "C" void *_start_wrapper(void *arg);  
   
 inline ThreadStatus Thread::run()  
 {  
     StartWrapperArg *arg = new StartWrapperArg;  
     arg->start = _start;  
     arg->arg = this;  
   
     Threads::Type type = _is_detached ? Threads::DETACHED : Threads::JOINABLE;  
     int rc = Threads::create(_handle.thid, type, _start_wrapper, arg);  
   
     // On Linux distributions released prior 2005, the implementation of  
     // Native POSIX Thread Library returns ENOMEM instead of EAGAIN when  
     // there  
     // are no insufficient memory.  Hence we are checking for both.  See bug  
     // 386.  
   
     if ((rc == EAGAIN) || (rc == ENOMEM))  
     {  
         Threads::clear(_handle.thid);  
         delete arg;  
         return PEGASUS_THREAD_INSUFFICIENT_RESOURCES;  
     }  
     else if (rc != 0)  
     {  
         Threads::clear(_handle.thid);  
         delete arg;  
         return PEGASUS_THREAD_SETUP_FAILURE;  
     }  
     return PEGASUS_THREAD_OK;  
 }  
   
 inline void Thread::cancel()  
 {  
     _cancelled = true;  
     pthread_cancel(_handle.thid.tt_handle());  
 }  
   
 inline void Thread::test_cancel()  
 {  
 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)  
     pthread_testintr();  
 #else  
     pthread_testcancel();  
 #endif  
 }  
   
 inline Boolean Thread::is_cancelled(void)  
 {  
     return _cancelled;  
 }  
   
 inline void Thread::thread_switch()  
 {  
 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)  
     pthread_yield(NULL);  
 #else  
     sched_yield();  
 #endif  
 }  
   
 /*  
 ATTN: why are these missing on other platforms?  
 */  
 #if defined(PEGASUS_PLATFORM_LINUX_GENERIC_GNU)  
 inline void Thread::suspend()  
 {  
     pthread_kill(_handle.thid.tt_handle(), SIGSTOP);  
 }  
   
 inline void Thread::resume()  
 {  
     pthread_kill(_handle.thid.tt_handle(), SIGCONT);  
 }  
 #endif  
   
 inline void Thread::sleep(Uint32 msec)  
 {  
     Threads::sleep(msec);  
 }  
   
 inline void Thread::join(void)  
 {  
     if (!_is_detached && Threads::id(_handle.thid) != 0)  
         pthread_join(_handle.thid.tt_handle(), &_exit_code);  
   
     Threads::clear(_handle.thid);  
 }  
   
 inline void Thread::thread_init(void)  
 {  
 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)  
     pthread_setintr(PTHREAD_INTR_ENABLE);  
     pthread_setintrtype(PTHREAD_INTR_ASYNCHRONOUS);  
 #else  
     pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);  
     pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);  
 #endif  
     _cancel_enabled = true;  
 }  
   
 inline void Thread::detach(void)  
 {  
     _is_detached = true;  
     pthread_detach(_handle.thid.tt_handle());  
 }  
   
 #endif /* PEGASUS_HAVE_PTHREADS */  
   
 //==============================================================================  
 //  
 // Windows Threads Implementation:  
 //  
 //==============================================================================  
   
 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)  
   
 inline ThreadStatus Thread::run(void)  
 {  
     // Note: A Win32 thread ID is not the same thing as a pthread ID.  
     // Win32 threads have both a thread ID and a handle.  The handle  
     // is used in the wait functions, etc.  
     // So _handle.thid is actually the thread handle.  
   
     unsigned threadid = 0;  
   
     ThreadType tt;  
     tt.handle = (HANDLE) _beginthreadex(NULL, 0, _start, this, 0, &threadid);  
     _handle.thid = tt;  
   
     if (Threads::id(_handle.thid) == 0)  
     {  
         if (errno == EAGAIN)  
         {  
             return PEGASUS_THREAD_INSUFFICIENT_RESOURCES;  
         }  
         else  
         {  
             return PEGASUS_THREAD_SETUP_FAILURE;  
         }  
     }  
     return PEGASUS_THREAD_OK;  
 }  
   
 inline void Thread::cancel(void)  
 {  
     _cancelled = true;  
 }  
   
 inline void Thread::test_cancel(void)  
 {  
     if (_cancel_enabled && _cancelled)  
     {  
         exit_self(0);  
     }  
 }  
   
 inline Boolean Thread::is_cancelled(void)  
 {  
     return _cancelled;  
 }  
   
 inline void Thread::thread_switch(void)  
 {  
     Sleep(0);  
 }  
   
 inline void Thread::sleep(Uint32 milliseconds)  
 {  
     Sleep(milliseconds);  
 }  
   
 inline void Thread::join(void)  
 {  
     if (Threads::id(_handle.thid) != 0)  
     {  
         if (!_is_detached)  
         {  
             if (!_cancelled)  
             {  
                 // Emulate the unix join api. Caller sleeps until thread is  
                 // done.  
                 WaitForSingleObject(_handle.thid.handle, INFINITE);  
             }  
             else  
             {  
                 // Currently this is the only way to ensure this code does  
                 // not  
                 // hang forever.  
                 if (WaitForSingleObject(_handle.thid.handle, 10000) ==  
                     WAIT_TIMEOUT)  
                 {  
                     TerminateThread(_handle.thid.handle, 0);  
                 }  
             }  
   
             DWORD exit_code = 0;  
             GetExitCodeThread(_handle.thid.handle, &exit_code);  
             _exit_code = (ThreadReturnType) exit_code;  
         }  
   
         CloseHandle(_handle.thid.handle);  
         Threads::clear(_handle.thid);  
     }  
 }  
   
 inline void Thread::thread_init(void)  
 {  
     _cancel_enabled = true;  
 }  
   
 inline void Thread::detach(void)  
 {  
     _is_detached = true;  
 }  
   
 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */  
   
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END
   
 #endif // Pegasus_Thread_h #endif // Pegasus_Thread_h


Legend:
Removed from v.1.57.2.4  
changed lines
  Added in v.1.69

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2