(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.1.2.1 and 1.69

version 1.1.2.1, 2001/07/30 12:06:14 version 1.69, 2009/08/13 13:13:07
Line 1 
Line 1 
 //%/////////////////////////////////////////////////////////////////////////////  //%LICENSE////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM  // Licensed to The Open Group (TOG) under one or more contributor license
   // agreements.  Refer to the OpenPegasusNOTICE.txt file distributed with
   // this work for additional information regarding copyright ownership.
   // Each contributor licenses this file to you under the OpenPegasus Open
   // Source License; you may not use this file except in compliance with the
   // License.
 // //
 // Permission is hereby granted, free of charge, to any person obtaining a copy  // Permission is hereby granted, free of charge, to any person obtaining a
 // of this software and associated documentation files (the "Software"), to  // copy of this software and associated documentation files (the "Software"),
 // deal in the Software without restriction, including without limitation the  // to deal in the Software without restriction, including without limitation
 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or  // the rights to use, copy, modify, merge, publish, distribute, sublicense,
 // sell copies of the Software, and to permit persons to whom the Software is  // and/or sell copies of the Software, and to permit persons to whom the
 // furnished to do so, subject to the following conditions:  // Software is furnished to do so, subject to the following conditions:
 //  
 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN  
 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED  
 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT  
 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR  
 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT  
 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN  
 // 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.  
 // //
 //==============================================================================  // The above copyright notice and this permission notice shall be included
   // in all copies or substantial portions of the Software.
 // //
 // Author: Mike Day (mdday@us.ibm.com)  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
   // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
   // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
   // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 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.
 // //
 // Modified By: Markus Mueller  //////////////////////////////////////////////////////////////////////////
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
   
 #ifndef Pegasus_Thread_h #ifndef Pegasus_Thread_h
 #define Pegasus_Thread_h #define Pegasus_Thread_h
  
 #include <Pegasus/Common/IPC.h>  #include <cstring>
 #include <Pegasus/Common/Config.h> #include <Pegasus/Common/Config.h>
 #include <Pegasus/Common/Exception.h>  #include <Pegasus/Common/AtomicInt.h>
 #include <Pegasus/Common/DQueue.h>  #include <Pegasus/Common/InternalException.h>
   #include <Pegasus/Common/AcceptLanguageList.h>
   #include <Pegasus/Common/Linkage.h>
   #include <Pegasus/Common/AutoPtr.h>
   #include <Pegasus/Common/List.h>
   #include <Pegasus/Common/Mutex.h>
   #include <Pegasus/Common/Semaphore.h>
   #include <Pegasus/Common/TSDKey.h>
   #include <Pegasus/Common/Threads.h>
   
   #if defined(PEGASUS_HAVE_PTHREADS)
   # include <signal.h>
   #endif
  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
 class PEGASUS_EXPORT cleanup_handler  class PEGASUS_COMMON_LINKAGE cleanup_handler : public Linkable
 { {
   
  public:  public:
   cleanup_handler( void (*routine)(void *), void *arg  ) : _routine(routine), _arg(arg)  {}      cleanup_handler(void (*routine) (void *), void *arg):_routine(routine),
   ~cleanup_handler() ;          _arg(arg)
       {
       }
       ~cleanup_handler()
       {;
       }
  
  private:  private:
   void execute(void) { _routine(_arg); }  
       void execute()
       {
           _routine(_arg);
       }
   
   cleanup_handler();   cleanup_handler();
   
   void (*_routine)(void *);   void (*_routine)(void *);
   inline Boolean operator==(void *key) { if(key == (void *)_routine) return true; return false; }  
   void *_arg;   void *_arg;
   PEGASUS_CLEANUP_HANDLE _cleanup_buffer;  
   friend class Dqueue;  
   friend class Thread;   friend class Thread;
 }; };
  
 /////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
  
 class PEGASUS_EXPORT SimpleThread  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:
   SimpleThread( PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *start )(void *),  
           void *parameter, Boolean detached );  
   
   ~SimpleThread();  
   
   void run(void);  
   
   Uint32 threadId(void);  
   
   // get the user parameter  
   void *get_parm(void);  
   
   // cancellation must be deferred (not asynchronous)  
   // for user-level threads the thread itself can decide  
   // when it should die.  
   void cancel(void);  
   
   void kill(int signum);  
   
   // cancel if there is a pending cancellation request  
   void test_cancel(void);  
   
   // for user-level threads  - put the calling thread  
   // to sleep and jump to the thread scheduler.  
   // platforms with preemptive scheduling and native threads  
   // can define this to be a no-op.  
   // platforms without preemptive scheduling like NetWare  
   // or gnu portable threads will have an existing  
   // routine that can be mapped to this method  
   
   void thread_switch(void);  
   
   // suspend this thread  
   void suspend(void) ;  
   
   // resume this thread  
   void resume(void) ;  
  
   void sleep(Uint32 msec) ;      static void default_delete(void *data)
       {
   // block the calling thread until this thread terminates          if (data)
   void join( PEGASUS_THREAD_RETURN *ret_val);              ::operator  delete(data);
       }
   
   // stack of functions to be called when thread terminates  
   // will be called last in first out (LIFO)  
   void cleanup_push( void (*routine) (void *), void *parm );  
   void cleanup_pop(Boolean execute) ;  
   
   PEGASUS_THREAD_TYPE self(void) ;  
   
  private:  
   SimpleThread();  
   
   PEGASUS_THREAD_HANDLE _handle;  
   Boolean _is_detached;  
   Boolean _cancel_enabled;  
   Boolean _cancelled;  
  
   //PEGASUS_SEM_HANDLE _suspend_count;      thread_data(TSD_Key key) : _delete_func(0), _data(0), _size(0), _key(key)
   Semaphore _suspend;      {
       }
  
   // always pass this * as the void * parameter to the thread      thread_data(TSD_Key key, size_t size) :
   // store the user parameter in _thread_parm          _delete_func(default_delete), _size(size), _key(key)
       {
           _data = ::operator  new(_size);
       }
  
   PEGASUS_THREAD_RETURN  ( PEGASUS_THREAD_CDECL *_start)(void *) ;      thread_data(TSD_Key key, size_t size, void* data)
           : _delete_func(default_delete), _size(size), _key(key)
       {
           _data = ::operator  new(_size);
           memcpy(_data, data, size);
       }
  
   void *_thread_parm;      ~thread_data()
 } ;      {
           if (_data && _delete_func)
               (*_delete_func)(_data);
       }
  
 ///////////////////////////////////////////////////////////////////////////////      /**
        * This function is used to put data in thread space.
        *
        * Be aware that there is NOTHING in place to stop
        * other users of the thread to remove this data.
        * Or change the data.
        *
        * You, the developer has to make sure that there are
        * no situations in which this can arise (ie, have a
        * lock for the function which manipulates the TSD.
        *
        * @exception NullPointer
       */
       void put_data(void (*del)(void *), size_t size, void* data)
       {
           if (_data && _delete_func)
               (*_delete_func)(_data);
  
 static void default_delete(void * data) { delete [] (char *) data; }          _delete_func = del;
           _data = data;
           _size = size;
       }
  
 class  PEGASUS_EXPORT thread_data      size_t get_size()
 { {
           return _size;
       }
  
  public:      void* get_data()
   thread_data( Sint8 *key ) : _delete_func(NULL) , _data(NULL)  
     {     {
       _key = strdup(key) ;          return _data;
     }     }
  
   thread_data(Sint8 *key, int size)      /**
           This function is used to retrieve data from the
           TSD, the thread specific data.
   
           Be aware that there is NOTHING in place to stop
           other users of the thread to change the data you
           get from this function.
   
           You, the developer has to make sure that there are
           no situations in which this can arise (ie, have a
           lock for the function which manipulates the TSD.
        */
       void get_data(void** data, size_t* size)
     {     {
       _delete_func = default_delete;          if (data == 0 || size == 0)
       _data = new char [size];              throw NullPointer();
   
           *data = _data;
           *size = _size;
     }     }
  
   thread_data(Sint8 *key, int size, void *data)      // @exception NullPointer
       void copy_data(void** buf, size_t* size)
     {     {
       _delete_func = default_delete;          if ((buf == 0) || (size == 0))
       _data = new char [size];              throw NullPointer();
       memcpy(_data, data, size);  
           *buf = ::operator new(_size);
           *size = _size;
           memcpy(*buf, _data, _size);
     }     }
  
   ~thread_data() { if( _data != NULL) _delete_func( _data ); }  
  
   void *get_data(Sint8 *key);  
   void *put_data(Sint8 *key, void (*delete_func) (void *), void *data  )  
     {  
       void *old_data = data;  
       _delete_func = delete_func;  
       _data = data;  
       return(old_data);  
     }  
  private:  private:
   inline Boolean operator ==(void *key) ;  
   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;
   Sint8 *_key;      size_t _size;
   friend class Dqueue;      TSD_Key _key;
   friend class Thread;  
 }; };
  
  
 class PEGASUS_EXPORT Thread  enum ThreadStatus
 { {
       PEGASUS_THREAD_OK = 1,      /* No problems */
       PEGASUS_THREAD_INSUFFICIENT_RESOURCES,      /* Can't allocate a thread.
                                                      Not enough memory. Try
                                                      again later */
       PEGASUS_THREAD_SETUP_FAILURE,       /* Could not allocate into the thread
                                              specific data storage. */
       PEGASUS_THREAD_UNAVAILABLE  /* Service is being destroyed and no new
                                      threads can be provided. */
   };
   
   ///////////////////////////////////////////////////////////////////////////
  
   class PEGASUS_COMMON_LINKAGE Thread : public Linkable
   {
  public:  public:
   Thread( PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *start )(void *),  
           void *parameter, Boolean detached );      Thread(
           ThreadReturnType(PEGASUS_THREAD_CDECL* start) (void*),
           void* parameter,
           Boolean detached);
  
   ~Thread();   ~Thread();
  
   void run(void);        /** Start the thread.
             @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 create properly - check the 'errno' value for specific operating
             system return code.
          */
       ThreadStatus run();
  
   // get the user parameter   // get the user parameter
   void *get_parm(void);      void *get_parm()
       {
   // send the thread a signal -- may not be appropriate due to Windows          return _thread_parm;
   void kill(int signum);      }
  
   // cancellation must be deferred (not asynchronous)   // cancellation must be deferred (not asynchronous)
   // for user-level threads the thread itself can decide   // for user-level threads the thread itself can decide
   // when it should die.   // when it should die.
   void cancel(void);      void cancel();
   
   // cancel if there is a pending cancellation request  
   void test_cancel(void);  
  
   // 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.
Line 211 
Line 286 
   // or gnu portable threads will have an existing   // or gnu portable threads will have an existing
   // routine that can be mapped to this method   // routine that can be mapped to this method
  
   void thread_switch(void);      void thread_switch();
   
   // suspend this thread  
   void suspend(void) ;  
  
   // resume this thread      static void sleep(Uint32 msec);
   void resume(void) ;  
   
   void sleep(Uint32 msec) ;  
  
   // block the calling thread until this thread terminates   // block the calling thread until this thread terminates
   void join(void );      void join();
  
       // thread routine needs to call this function when
       // it is ready to exit
       void exit_self(ThreadReturnType return_code);
  
   // 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)
   void cleanup_push( void (*routine) (void *), void *parm ) throw(IPCException);      void cleanup_push(void (*routine) (void *), void* parm);
   void cleanup_pop(Boolean execute = true) throw(IPCException);  
  
   // thread specific data (thread_data object methods)      void cleanup_pop(Boolean execute = true);
  
   void create_tsd(void *key ) ;      // get the buffer associated with the key
   void create_tsd(void *key, int size) ;      // NOTE: this call leaves the tsd LOCKED !!!!
   void *get_tsd(void *key);      void* reference_tsd(TSD_Key key)
   void delete_tsd(void *key);      {
   void * put_tsd(void *key, void (*delete_func)(void *), void *value);          if (_tsd[key])
               return _tsd[key]->get_data();
            else
               return 0;
       }
  
   inline PEGASUS_THREAD_RETURN get_exit(void) { return _exit_code; }      // release the lock held on the tsd
   inline PEGASUS_THREAD_TYPE self(void) {return _handle.thid; }      // NOTE: assumes a corresponding and prior call to reference_tsd() !!!
       void dereference_tsd()
       {
       }
  
  private:      // delete the tsd associated with the key
   Thread();      void delete_tsd(TSD_Key key)
       {
           thread_data* tsd;
  
   PEGASUS_THREAD_HANDLE _handle;          tsd = _tsd[key];
   Boolean _is_detached;          _tsd[key] = 0;
   Boolean _cancel_enabled;  
   Boolean _cancelled;  
  
   PEGASUS_SEM_HANDLE _suspend_count;          if (tsd)
               delete tsd;
       }
  
   // always pass this * as the void * parameter to the thread      void empty_tsd()
   // store the user parameter in _thread_parm      {
           thread_data* data[TSD_COUNT];
  
   PEGASUS_THREAD_RETURN  ( PEGASUS_THREAD_CDECL *_start)(void *) ;          memcpy(data, _tsd, sizeof(_tsd));
           memset(_tsd, 0, sizeof(_tsd));
  
   DQueue<cleanup_handler> _cleanup;          for (size_t i = 0; i < TSD_COUNT; i++)
   DQueue<thread_data> _tsd;          {
   void *_thread_parm;              if (data[i])
                   delete data[i];
           }
       }
   
       // create or re-initialize tsd associated with the key
       // if the tsd already exists, delete the existing buffer
       void put_tsd(
           TSD_Key key,
           void (*delete_func)(void*),
           Uint32 size,
           void* value)
       {
           thread_data* tsd = new thread_data(key);
           tsd->put_data(delete_func, size, value);
  
   PEGASUS_THREAD_RETURN _exit_code;          thread_data* old;
  
 } ;          old = _tsd[key];
           _tsd[key] = tsd;
  
           if (old)
               delete old;
       }
  
 #if 0      ThreadReturnType get_exit()
 class PEGASUS_EXPORT Aggregator {      {
           return _exit_code;
       }
  
  public:      ThreadType self()
       {
           return Threads::self();
       }
  
   Aggregator();      ThreadHandle getThreadHandle()
   ~Aggregator();      {
           return _handle;
       }
  
   void started(void);      Boolean isDetached()
   void completed(void);      {
   void remaining(int operations);          return _is_detached;
   void put_result(CIMReference *ref);      }
   
       void detach();
   
       //
       // Gets the Thread object associated with the caller's thread.
       // Note: this may return NULL if no Thread object is associated
       // with the caller's thread.
       //
       static Thread *getCurrent();
   
       //
       // Sets the Thread object associated with the caller's thread.
       // Note: the Thread object must be placed on the heap.
       //
       static void setCurrent(Thread* thrd);
   
       //
       // Gets the AcceptLanguageList object associated with the caller's
       // Thread.
       // Note: this may return NULL if no Thread object, or no
       // AcceptLanguageList object, is associated with the caller's thread.
       //
       static AcceptLanguageList* getLanguages();
   
       //
       // Sets the AcceptLanguageList object associated with the caller's
       // Thread.
       // Note: a Thread object must have been previously associated with
       // the caller's thread.
       //
       static void setLanguages(const AcceptLanguageList& langs);
   
       //
       // Removes the AcceptLanguageList object associated with the caller's
       // Thread.
       //
       static void clearLanguages();
  
  private:  private:
   int _reference_count;      Thread();
   
       static Sint8 initializeKey();
  
   // keep track of the thread running this operation so we can kill      ThreadHandle _handle;
   // it if necessary      Boolean _is_detached;
   Thread _owner;      Boolean _cancelled;
   
   // this is a phased aggregate. when it is complete is will      // always pass this * as the void * parameter to the thread
   // be streamed to the client regardless of the state of      // store the user parameter in _thread_parm
   // siblings  
   Boolean _is_phased;      ThreadReturnType(PEGASUS_THREAD_CDECL* _start) (void *);
       List<cleanup_handler, Mutex> _cleanup;
   int _total_values;      thread_data* _tsd[TSD_COUNT];
   int _completed_values;  
   int _total_child_values;      void* _thread_parm;
   int _completed_child_values;      ThreadReturnType _exit_code;
   int _completion_state;      static Boolean _signals_blocked;
   struct timeval _last_update;      static TSDKeyType _platform_thread_key;
   time_t lifetime;      static Boolean _key_initialized;
   Aggregator *_parent;      static Boolean _key_error;
   // children may be phased or not phased  
   DQueue _children;  
   // empty results that are filled by provider  
   DQueue _results;  
   // array of predicates for events and  
   // stored queries (cursors)  
   Array _filter;  
 } ; } ;
 #endif  
  
 PEGASUS_NAMESPACE_END PEGASUS_NAMESPACE_END
  


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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2