version 1.15, 2002/05/21 04:07:12
|
version 1.24, 2002/09/17 18:01:03
|
|
|
//%///////////-*-c++-*-////////////////////////////////////////////////////// |
//%/-*-c++-*-//////////////////////////////////////////////////////////////////////////// |
// | // |
// Copyright (c) 2000, 2001 The Open group, BMC Software, Tivoli Systems, IBM |
// Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM, |
|
// The Open Group, Tivoli Systems |
// | // |
// 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 copy |
// of this software and associated documentation files (the "Software"), to | // of this software and associated documentation files (the "Software"), to |
|
|
#define Pegasus_Thread_h | #define Pegasus_Thread_h |
#include <Pegasus/Common/Config.h> | #include <Pegasus/Common/Config.h> |
#include <Pegasus/Common/IPC.h> | #include <Pegasus/Common/IPC.h> |
#include <Pegasus/Common/Exception.h> |
#include <Pegasus/Common/InternalException.h> |
#include <Pegasus/Common/DQueue.h> | #include <Pegasus/Common/DQueue.h> |
|
#include <Pegasus/Common/Linkage.h> |
// REVIEW: Spend time getting to know this. |
|
| |
PEGASUS_NAMESPACE_BEGIN | PEGASUS_NAMESPACE_BEGIN |
| |
|
|
| |
} | } |
| |
void copy_data(void **buf, size_t *size) throw(BufferTooSmall, NullPointer) |
void copy_data(void **buf, size_t *size) throw(NullPointer) |
{ | { |
if((buf == NULL) || (size == NULL)) | if((buf == NULL) || (size == NULL)) |
throw NullPointer() ; | throw NullPointer() ; |
|
|
void cancel(void); | void cancel(void); |
| |
// cancel if there is a pending cancellation request | // cancel if there is a pending cancellation request |
void test_cancel(void); |
static void test_cancel(void); |
| |
Boolean is_cancelled(void); | Boolean is_cancelled(void); |
| |
|
|
| |
// 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) ; |
static void exit_self(PEGASUS_THREAD_RETURN 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) |
|
|
inline void empty_tsd(void) throw(IPCException) | inline void empty_tsd(void) throw(IPCException) |
{ | { |
thread_data* tsd; | thread_data* tsd; |
while (tsd = _tsd.remove_first()) |
while (0 != (tsd = _tsd.remove_first())) |
{ | { |
delete tsd; | delete tsd; |
} | } |
|
|
return _running.count(); | return _running.count(); |
} | } |
| |
|
inline Uint32 pool_count(void) |
|
{ |
|
return _pool.count(); |
|
} |
|
inline Uint32 dead_count(void) |
|
{ |
|
return _dead.count(); |
|
} |
|
|
|
|
static Boolean check_time(struct timeval *start, struct timeval *interval); | static Boolean check_time(struct timeval *start, struct timeval *interval); |
| |
|
Boolean operator ==(const ThreadPool & p) |
|
{ |
|
return operator==((const void *)&p); |
|
} |
|
|
|
Boolean operator ==(const void *p) |
|
{ |
|
if((void *)this == p) |
|
return true; |
|
return false; |
|
} |
|
|
|
static void kill_idle_threads(void); |
|
|
private: | private: |
ThreadPool(void); | ThreadPool(void); |
Sint16 _max_threads; | Sint16 _max_threads; |
|
|
DQueue<Thread> _running; | DQueue<Thread> _running; |
DQueue<Thread> _dead; | DQueue<Thread> _dead; |
AtomicInt _dying; | AtomicInt _dying; |
|
|
|
|
static void _sleep_sem_del(void *p); | static void _sleep_sem_del(void *p); |
| |
void _check_deadlock(struct timeval *start) throw(Deadlock); | void _check_deadlock(struct timeval *start) throw(Deadlock); |
|
|
Thread *_init_thread(void) throw(IPCException); | Thread *_init_thread(void) throw(IPCException); |
void _link_pool(Thread *th) throw(IPCException); | void _link_pool(Thread *th) throw(IPCException); |
static PEGASUS_THREAD_RETURN _undertaker(void *); | static PEGASUS_THREAD_RETURN _undertaker(void *); |
|
static DQueue<ThreadPool> _pools; |
}; | }; |
| |
| |
inline void ThreadPool::_sleep_sem_del(void *p) |
|
{ |
|
if(p != 0) |
|
{ |
|
delete (Semaphore *)p; |
|
} |
|
} |
|
|
|
inline void ThreadPool::_check_deadlock(struct timeval *start) throw(Deadlock) |
|
{ |
|
if (true == check_time(start, &_deadlock_detect)) |
|
throw Deadlock(pegasus_thread_self()); |
|
return; |
|
} |
|
|
|
|
|
inline Boolean ThreadPool::_check_deadlock_no_throw(struct timeval *start) |
|
{ |
|
return(check_time(start, &_deadlock_detect)); |
|
} |
|
|
|
inline Boolean ThreadPool::_check_dealloc(struct timeval *start) |
|
{ |
|
return(check_time(start, &_deallocate_wait)); |
|
} |
|
|
|
inline Thread *ThreadPool::_init_thread(void) throw(IPCException) |
|
{ |
|
Thread *th = (Thread *) new Thread(_loop, this, false); |
|
// allocate a sleep semaphore and pass it in the thread context |
|
// initial count is zero, loop function will sleep until |
|
// we signal the semaphore |
|
Semaphore *sleep_sem = (Semaphore *) new Semaphore(0); |
|
th->put_tsd("sleep sem", &_sleep_sem_del, sizeof(Semaphore), (void *)sleep_sem); |
|
|
|
struct timeval *dldt = (struct timeval *) ::operator new(sizeof(struct timeval)); |
|
th->put_tsd("deadlock timer", thread_data::default_delete, sizeof(struct timeval), (void *)dldt); |
|
// thread will enter _loop(void *) and sleep on sleep_sem until we signal it |
|
th->run(); |
|
_current_threads++; |
|
pegasus_yield(); |
|
|
|
return th; |
|
} |
|
|
|
inline void ThreadPool::_link_pool(Thread *th) throw(IPCException) |
|
{ |
|
if(th == 0) |
|
throw NullPointer(); |
|
_pool.insert_first(th); |
|
} |
|
| |
| |
#if defined(PEGASUS_OS_TYPE_WINDOWS) | #if defined(PEGASUS_OS_TYPE_WINDOWS) |