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

File: [Pegasus] / pegasus / src / Pegasus / Common / Thread.h (download)
Revision: 1.1.2.5, Tue Jul 31 11:54:35 2001 UTC (22 years, 11 months ago) by mday
Branch: dev
CVS Tags: version_1_01
Changes since 1.1.2.4: +17 -5 lines
fixed problems with doubly-linked list template class

//%/////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to 
// deal in the Software without restriction, including without limitation the 
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
// sell copies of the Software, and to permit persons to whom the 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.
//
//==============================================================================
//
// Author: Mike Day (mdday@us.ibm.com)
//
// Modified By: Markus Mueller
//
//%/////////////////////////////////////////////////////////////////////////////


#ifndef Pegasus_Thread_h
#define Pegasus_Thread_h

#include <Pegasus/Common/IPC.h>
#include <Pegasus/Common/Config.h>
#include <Pegasus/Common/Exception.h>
#include <Pegasus/Common/DQueue.h>

PEGASUS_NAMESPACE_BEGIN

class PEGASUS_EXPORT cleanup_handler
{

 public:
  cleanup_handler( void (*routine)(void *), void *arg  ) : _routine(routine), _arg(arg)  {}
  ~cleanup_handler()  {; }

 private:
  void execute(void) { _routine(_arg); } 
  cleanup_handler();
  void (*_routine)(void *);
  inline Boolean operator==(void *key) { if(key == (void *)_routine) return true; return false; }
  void *_arg; 
  PEGASUS_CLEANUP_HANDLE _cleanup_buffer;
  template<class cleanup_handler> friend class DQueue;
  friend class Thread;
};

///////////////////////////////////////////////////////////////////////////////

class PEGASUS_EXPORT SimpleThread
{

 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) ;

  // block the calling thread until this thread terminates
  void join( PEGASUS_THREAD_RETURN *ret_val);


  // 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;
  Semaphore _suspend;

  // always pass this * as the void * parameter to the thread
  // store the user parameter in _thread_parm 

  PEGASUS_THREAD_RETURN  ( PEGASUS_THREAD_CDECL *_start)(void *) ;

  void *_thread_parm;
} ;

///////////////////////////////////////////////////////////////////////////////

static void default_delete(void * data) { delete [] (char *) data; }

class  PEGASUS_EXPORT thread_data
{

 public:
  thread_data( Sint8 *key ) : _delete_func(NULL) , _data(NULL), _size(0)
  {
    PEGASUS_ASSERT(key != NULL);
    _key = strdup(key) ; 
  }
  
  thread_data(Sint8 *key, int size)
  {
    PEGASUS_ASSERT(key != NULL);
    _delete_func = default_delete;
    _data = new char [size];
    _size = size;
  }

  thread_data(Sint8 *key, int size, void *data)
  {
    PEGASUS_ASSERT(key != NULL);
    PEGASUS_ASSERT(data != NULL);
    _delete_func = default_delete;
    _data = new char [size];
    memcpy(_data, data, size);
    _size = size;
  }

  ~thread_data() { if( _data != NULL) _delete_func( _data ); }  

  void *get_data(void );
  Uint32 get_size(void);
  void *put_data(void (*delete_func) (void *), Uint32 size, void *data  )
    {
      void *old_data = data;
      _delete_func = delete_func;
      _data = data;
      _size = size;
      return(old_data);
    }

 private:
  inline Boolean operator ==(void *key) { if ( ! strcmp(_key, (Sint8 *)key)) return(true); return(false);  } 
  void (*_delete_func) (void *data) ;
  thread_data();
  void *_data;
  Uint32 _size;
  Sint8 *_key;
  
  template<class thread_data> friend class DQueue;
  friend class Thread;
};


///////////////////////////////////////////////////////////////////////////

class PEGASUS_EXPORT Thread
{

 public:
  Thread( PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *start )(void *),
          void *parameter, Boolean detached );

  ~Thread();

  void run(void);

  // get the user parameter 
  inline void *get_parm(void) { return _thread_parm; }

  // send the thread a signal -- may not be appropriate due to Windows 
  //  void kill(int signum); 

  // cancellation must be deferred (not asynchronous)
  // for user-level threads the thread itself can decide
  // when it should die. 
  void cancel(void);

  // 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) ;

  // block the calling thread until this thread terminates
  void join(void );
  void thread_init(void);

  // thread routine needs to call this function when
  // it is ready to exit
  void exit_self(PEGASUS_THREAD_RETURN return_code) ;

  // 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 ) throw(IPCException);
  void cleanup_pop(Boolean execute = true) throw(IPCException);

  // create and initialize a tsd
  inline void create_tsd(Sint8 *key, int size, void *buffer) throw(IPCException)
  {
    thread_data *tsd = new thread_data(key, size, buffer);
       try { _tsd.insert_first(tsd); }
    catch(IPCException& e) { delete tsd; throw; }
  }

  // get the buffer associated with the key
  // NOTE: this call leaves the tsd LOCKED !!!! 
  inline void *reference_tsd(Sint8 *key) throw(IPCException)
  {
    _tsd.lock(); 
    thread_data *tsd = _tsd.reference((void *)key);
    if(tsd != NULL)
      return( (void *)(tsd->_data) );
    else
      return(NULL);
  }

  // release the lock held on the tsd
  // NOTE: assumes a corresponding and prior call to reference_tsd() !!!
  inline void dereference_tsd(void) throw(IPCException)
  {
     _tsd.unlock();
  }

  // delete the tsd associated with the key
  inline void delete_tsd(Sint8 *key) throw(IPCException)
  {
    thread_data *tsd = _tsd.remove((void *)key);
    if(tsd != NULL)
      delete tsd;
  }

  // create or re-initialize tsd associated with the key
  // if the tsd already exists, return the existing buffer
  thread_data *put_tsd(Sint8 *key, void (*delete_func)(void *), Uint32 size, void *value) throw(IPCException)

{
  PEGASUS_ASSERT(key != NULL);
  PEGASUS_ASSERT(delete_func != NULL);
  thread_data *tsd ;
  tsd = _tsd.remove((void *)key);  // may throw an IPC exception 
  thread_data *ntsd = new thread_data(key);
  ntsd->put_data(delete_func, size, value);
  try { _tsd.insert_first(ntsd); }
  catch(IPCException& e) { delete ntsd; throw; }
  return(tsd);
}
  inline PEGASUS_THREAD_RETURN get_exit(void) { return _exit_code; }
  inline PEGASUS_THREAD_TYPE self(void) {return pegasus_thread_self(); }

 private:
  Thread();
  inline void create_tsd(Sint8 *key ) throw(IPCException)
  {
    thread_data *tsd = new thread_data(key);
    try { _tsd.insert_first(tsd); }
    catch(IPCException& e) { delete tsd; throw; }
  }
  PEGASUS_THREAD_HANDLE _handle;
  Boolean _is_detached;
  Boolean _cancel_enabled;
  Boolean _cancelled; 
  
  PEGASUS_SEM_HANDLE _suspend_count;

  // always pass this * as the void * parameter to the thread
  // store the user parameter in _thread_parm 

  PEGASUS_THREAD_RETURN  ( PEGASUS_THREAD_CDECL *_start)(void *) ;
  DQueue<cleanup_handler> _cleanup;
  DQueue<thread_data> _tsd;

  void *_thread_parm;
  PEGASUS_THREAD_RETURN _exit_code;
  static Boolean _signals_blocked;
} ;


#if 0
class PEGASUS_EXPORT Aggregator {

 public:

  Aggregator();
  ~Aggregator();

  void started(void);
  void completed(void);
  void remaining(int operations);
  void put_result(CIMReference *ref);

 private: 
  int _reference_count;

  // keep track of the thread running this operation so we can kill
  // it if necessary 
  Thread _owner;

  // this is a phased aggregate. when it is complete is will
  // be streamed to the client regardless of the state of 
  // siblings 
  Boolean _is_phased;

  int _total_values;
  int _completed_values;
  int _total_child_values;
  int _completed_child_values;
  int _completion_state;
  struct timeval _last_update; 
  time_t lifetime;
  Aggregator *_parent;
  // 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

#endif // Pegasus_Thread_h

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2