version 1.57, 2006/07/12 19:46:26
|
version 1.57.2.5, 2006/07/29 01:13:49
|
|
|
| |
#include <cstring> | #include <cstring> |
#include <Pegasus/Common/Config.h> | #include <Pegasus/Common/Config.h> |
#include <Pegasus/Common/IPC.h> |
#include <Pegasus/Common/AtomicInt.h> |
#include <Pegasus/Common/InternalException.h> | #include <Pegasus/Common/InternalException.h> |
#include <Pegasus/Common/AcceptLanguageList.h> | #include <Pegasus/Common/AcceptLanguageList.h> |
#include <Pegasus/Common/Linkage.h> | #include <Pegasus/Common/Linkage.h> |
#include <Pegasus/Common/AutoPtr.h> | #include <Pegasus/Common/AutoPtr.h> |
#include <Pegasus/Common/List.h> | #include <Pegasus/Common/List.h> |
#include <Pegasus/Common/RecursiveMutex.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_COMMON_LINKAGE cleanup_handler : public Linkable | 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() { _routine(_arg); } |
|
|
void execute() |
|
{ |
|
_routine(_arg); |
|
} |
|
|
cleanup_handler(); | cleanup_handler(); |
void (*_routine)(void *); |
|
| |
|
void (*_routine)(void*); |
void *_arg; | void *_arg; |
PEGASUS_CLEANUP_HANDLE _cleanup_buffer; |
|
friend class Thread; | friend class Thread; |
}; | }; |
| |
/////////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////////// |
| |
|
|
class PEGASUS_COMMON_LINKAGE thread_data : public Linkable | class PEGASUS_COMMON_LINKAGE thread_data : public Linkable |
{ | { |
|
|
public: | public: |
|
|
static void default_delete(void *data); | static void default_delete(void *data); |
| |
thread_data( const char *key ) : _delete_func(NULL) , _data(NULL), _size(0) | thread_data( const char *key ) : _delete_func(NULL) , _data(NULL), _size(0) |
|
|
_key.reset(new char[keysize + 1]); | _key.reset(new char[keysize + 1]); |
memcpy(_key.get(), key, keysize); | memcpy(_key.get(), key, keysize); |
_key.get()[keysize] = 0x00; | _key.get()[keysize] = 0x00; |
|
|
} | } |
| |
thread_data(const char *key, size_t size) : _delete_func(default_delete), _size(size) |
thread_data(const char *key, size_t size) : |
|
_delete_func(default_delete), _size(size) |
{ | { |
PEGASUS_ASSERT(key != NULL); | PEGASUS_ASSERT(key != NULL); |
size_t keysize = strlen(key); | size_t keysize = strlen(key); |
|
|
memcpy(_key.get(), key, keysize); | memcpy(_key.get(), key, keysize); |
_key.get()[keysize] = 0x00; | _key.get()[keysize] = 0x00; |
_data = ::operator new(_size); | _data = ::operator new(_size); |
|
|
} | } |
| |
thread_data(const char *key, size_t size, void *data) : _delete_func(default_delete), _size(size) |
thread_data(const char *key, size_t size, void *data) : |
|
_delete_func(default_delete), _size(size) |
{ | { |
PEGASUS_ASSERT(key != NULL); | PEGASUS_ASSERT(key != NULL); |
PEGASUS_ASSERT(data != NULL); | PEGASUS_ASSERT(data != NULL); |
|
|
return; | return; |
} | } |
| |
size_t get_size() { return _size; } |
size_t get_size() |
|
{ |
|
return _size; |
|
} |
| |
/** | /** |
* This function is used to retrieve data from the | * This function is used to retrieve data from the |
|
|
}; | }; |
| |
| |
enum ThreadStatus { |
enum ThreadStatus |
|
{ |
PEGASUS_THREAD_OK = 1, /* No problems */ | PEGASUS_THREAD_OK = 1, /* No problems */ |
PEGASUS_THREAD_INSUFFICIENT_RESOURCES, /* Can't allocate a thread. Not enough |
PEGASUS_THREAD_INSUFFICIENT_RESOURCES, /* Can't allocate a thread. |
memory. Try again later */ |
Not enough memory. Try |
PEGASUS_THREAD_SETUP_FAILURE, /* Could not allocate into the thread specific |
again later */ |
data storage. */ |
PEGASUS_THREAD_SETUP_FAILURE, /* Could not allocate into the thread |
PEGASUS_THREAD_UNAVAILABLE /* Service is being destroyed and no new threads can |
specific data storage. */ |
be provided. */ |
PEGASUS_THREAD_UNAVAILABLE /* Service is being destroyed and no new |
|
threads can be provided. */ |
}; | }; |
| |
/////////////////////////////////////////////////////////////////////////// | /////////////////////////////////////////////////////////////////////////// |
|
|
{ | { |
public: | public: |
| |
Thread( PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL *start )(void *), |
Thread(ThreadReturnType(PEGASUS_THREAD_CDECL * start) (void *), |
void *parameter, Boolean detached ); | void *parameter, Boolean detached ); |
| |
~Thread(); | ~Thread(); |
| |
/** |
/** Start the thread. |
Start the thread. |
|
@return PEGASUS_THREAD_OK if the thread is started successfully, | @return PEGASUS_THREAD_OK if the thread is started successfully, |
PEGASUS_THREAD_INSUFFICIENT_RESOURCES if the resources necessary | PEGASUS_THREAD_INSUFFICIENT_RESOURCES if the resources necessary |
to start the thread are not currently available. | to start the thread are not currently available. |
|
|
ThreadStatus run(); | ThreadStatus run(); |
| |
// get the user parameter | // get the user parameter |
inline void *get_parm() { return _thread_parm; } |
inline void *get_parm() |
|
{ |
|
return _thread_parm; |
|
} |
| |
// 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 |
|
|
| |
// 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 |
void exit_self(PEGASUS_THREAD_RETURN return_code); |
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) |
|
|
// 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 | // @exception IPCException |
void put_tsd(const char *key, void (*delete_func)(void *), Uint32 size, void *value) |
void put_tsd(const char *key, void (*delete_func) (void *), Uint32 size, |
|
void *value) |
{ | { |
PEGASUS_ASSERT(key != NULL); | PEGASUS_ASSERT(key != NULL); |
AutoPtr<thread_data> tsd; | AutoPtr<thread_data> tsd; |
tsd.reset(_tsd.remove(thread_data::equal, key)); // may throw an IPC exception |
tsd.reset(_tsd.remove(thread_data::equal, key)); // may throw |
|
// an IPC |
|
// exception |
tsd.reset(); | tsd.reset(); |
AutoPtr<thread_data> ntsd(new thread_data(key)); | AutoPtr<thread_data> ntsd(new thread_data(key)); |
ntsd->put_data(delete_func, size, value); | ntsd->put_data(delete_func, size, value); |
try { _tsd.insert_front(ntsd.get()); } |
try |
catch(IPCException& e) { e = e; throw; } |
{ |
|
_tsd.insert_front(ntsd.get()); |
|
} |
|
catch(IPCException & e) |
|
{ |
|
e = e; |
|
throw; |
|
} |
ntsd.release(); | ntsd.release(); |
} | } |
inline PEGASUS_THREAD_RETURN get_exit() { return _exit_code; } |
inline ThreadReturnType get_exit() |
inline PEGASUS_THREAD_TYPE self() {return pegasus_thread_self(); } |
{ |
|
return _exit_code; |
|
} |
|
inline ThreadType self() |
|
{ |
|
return Threads::self(); |
|
} |
| |
PEGASUS_THREAD_HANDLE getThreadHandle() {return _handle;} |
ThreadHandle getThreadHandle() |
|
{ |
|
return _handle; |
|
} |
| |
void detach(); | void detach(); |
| |
|
|
_tsd.insert_front(tsd.get()); | _tsd.insert_front(tsd.get()); |
tsd.release(); | tsd.release(); |
} | } |
PEGASUS_THREAD_HANDLE _handle; |
ThreadHandle _handle; |
Boolean _is_detached; | Boolean _is_detached; |
Boolean _cancel_enabled; | Boolean _cancel_enabled; |
Boolean _cancelled; | Boolean _cancelled; |
| |
PEGASUS_SEM_HANDLE _suspend_count; |
|
|
|
// always pass this * as the void * parameter to the thread | // always pass this * as the void * parameter to the thread |
// store the user parameter in _thread_parm | // store the user parameter in _thread_parm |
| |
PEGASUS_THREAD_RETURN ( PEGASUS_THREAD_CDECL *_start)(void *); |
ThreadReturnType(PEGASUS_THREAD_CDECL * _start) (void *); |
List<cleanup_handler, RecursiveMutex> _cleanup; |
List < cleanup_handler, Mutex > _cleanup; |
List<thread_data, RecursiveMutex> _tsd; |
List < thread_data, Mutex > _tsd; |
| |
void *_thread_parm; | void *_thread_parm; |
PEGASUS_THREAD_RETURN _exit_code; |
ThreadReturnType _exit_code; |
static Boolean _signals_blocked; | static Boolean _signals_blocked; |
static PEGASUS_THREAD_KEY_TYPE _platform_thread_key; //l10n |
static TSDKeyType _platform_thread_key; // l10n |
static Boolean _key_initialized; // l10n | static Boolean _key_initialized; // l10n |
static Boolean _key_error; // l10n | static Boolean _key_error; // l10n |
}; | }; |
|
|
@param deallocateWait The minimum time that a thread should be idle | @param deallocateWait The minimum time that a thread should be idle |
before it is removed from the pool and cleaned up. | before it is removed from the pool and cleaned up. |
*/ | */ |
ThreadPool( |
ThreadPool(Sint16 initialSize, |
Sint16 initialSize, |
|
const char* key, | const char* key, |
Sint16 minThreads, | Sint16 minThreads, |
Sint16 maxThreads, |
Sint16 maxThreads, struct timeval &deallocateWait); |
struct timeval& deallocateWait); |
|
| |
/** | /** |
Destructs the ThreadPool object. | Destructs the ThreadPool object. |
|
|
be allocated. | be allocated. |
@exception IPCException | @exception IPCException |
*/ | */ |
ThreadStatus allocate_and_awaken( |
ThreadStatus allocate_and_awaken(void *parm, |
void* parm, |
ThreadReturnType(PEGASUS_THREAD_CDECL * |
PEGASUS_THREAD_RETURN (PEGASUS_THREAD_CDECL* work)(void *), |
work) (void *), |
Semaphore* blocking = 0); | Semaphore* blocking = 0); |
| |
/** | /** |
|
|
ThreadPool(const ThreadPool&); // Unimplemented | ThreadPool(const ThreadPool&); // Unimplemented |
ThreadPool& operator=(const ThreadPool&); // Unimplemented | ThreadPool& operator=(const ThreadPool&); // Unimplemented |
| |
static PEGASUS_THREAD_RETURN PEGASUS_THREAD_CDECL _loop(void *); |
static ThreadReturnType PEGASUS_THREAD_CDECL _loop(void *); |
| |
static Boolean _timeIntervalExpired( |
static Boolean _timeIntervalExpired(struct timeval *start, |
struct timeval* start, |
|
struct timeval* interval); | struct timeval* interval); |
| |
static void _deleteSemaphore(void* p); | static void _deleteSemaphore(void* p); |
|
|
AtomicInt _currentThreads; | AtomicInt _currentThreads; |
struct timeval _deallocateWait; | struct timeval _deallocateWait; |
char _key[17]; | char _key[17]; |
List<Thread, RecursiveMutex> _idleThreads; |
List < Thread, Mutex > _idleThreads; |
List<Thread, RecursiveMutex> _runningThreads; |
List < Thread, Mutex > _runningThreads; |
AtomicInt _dying; | AtomicInt _dying; |
}; | }; |
| |
|
|
#if defined(PEGASUS_OS_TYPE_WINDOWS) |
|
# include "ThreadWindows_inline.h" |
|
#elif defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM) |
|
# include "ThreadzOS_inline.h" |
|
#elif defined(PEGASUS_OS_TYPE_UNIX) |
|
# include "ThreadUnix_inline.h" |
|
#elif defined(PEGASUS_OS_VMS) |
|
# include "ThreadVms_inline.h" |
|
#endif |
|
|
|
PEGASUS_NAMESPACE_END | PEGASUS_NAMESPACE_END |
|
|
#endif // Pegasus_Thread_h | #endif // Pegasus_Thread_h |