#include <ace/Thread_Manager.h>
class ACE_Thread_Manager {
public:friend class ACE_Thread_Control;friend class ACE_Thread_Descriptor;typedef int (ACE_Thread_Manager::*ACE_THR_MEMBER_FUNC)( ACE_Thread_Descriptor *, int );enum{ ACE_THR_IDLE = 0x00000000, ACE_THR_SPAWNED = 0x00000001, ACE_THR_RUNNING = 0x00000002, ACE_THR_SUSPENDED = 0x00000004, ACE_THR_CANCELLED = 0x00000008, ACE_THR_TERMINATED = 0x00000010, ACE_THR_JOINING = 0x10000000 };ACE_Thread_Manager ( size_t preaolloc = 0, size_t lwm = ACE_DEFAULT_THREAD_MANAGER_LWM, size_t inc = ACE_DEFAULT_THREAD_MANAGER_INC, size_t hwm = ACE_DEFAULT_THREAD_MANAGER_HWM );virtual ~ACE_Thread_Manager (void);static ACE_Thread_Manager *instance (void);static ACE_Thread_Manager *instance (ACE_Thread_Manager *);static void close_singleton (void);int open (size_t size = 0);int close ();int spawn ( ACE_THR_FUNC func, void *args = 0, long flags = THR_NEW_LWP | THR_JOINABLE, ACE_thread_t * = 0, ACE_hthread_t *t_handle = 0, long priority = ACE_DEFAULT_THREAD_PRIORITY, int grp_id = -1, void *stack = 0, size_t stack_size = 0 );int spawn_n ( size_t n, ACE_THR_FUNC func, void *args = 0, long flags = THR_NEW_LWP | THR_JOINABLE, long priority = ACE_DEFAULT_THREAD_PRIORITY, int grp_id = -1, ACE_Task_Base *task = 0, ACE_hthread_t thread_handles[] = 0, void *stack[] = 0, size_t stack_size[] = 0 );int spawn_n ( ACE_thread_t thread_ids[], size_t n, ACE_THR_FUNC func, void *args, long flags, long priority = ACE_DEFAULT_THREAD_PRIORITY, int grp_id = -1, void *stack[] = 0, size_t stack_size[] = 0, ACE_hthread_t thread_handles[] = 0 );void *exit (void *status, int do_thread_exit = 1);int wait ( const ACE_Time_Value *timeout = 0, int abandon_detached_threads = 0 );int join (ACE_thread_t tid, void **status = 0);int wait_grp (int grp_id);ACE_Thread_Descriptor *thread_desc_self (void);ACE_Thread_Descriptor *thread_descriptor (ACE_thread_t);ACE_Thread_Descriptor *hthread_descriptor (ACE_hthread_t);int thr_self (ACE_hthread_t &);ACE_thread_t thr_self (void);ACE_Task_Base *task (void);int suspend_all (void);int suspend (ACE_thread_t);int suspend_grp (int grp_id);int testsuspend (ACE_thread_t t_id);int resume_all (void);int resume (ACE_thread_t);int resume_grp (int grp_id);int testresume (ACE_thread_t t_id);int kill_all (int signum);int kill (ACE_thread_t, int signum);int kill_grp (int grp_id, int signum);int cancel_all (int async_cancel = 0);int cancel (ACE_thread_t, int async_cancel = 0);int cancel_grp (int grp_id, int async_cancel = 0);int testcancel (ACE_thread_t t_id);int set_grp (ACE_thread_t, int grp_id);int get_grp (ACE_thread_t, int &grp_id);int wait_task (ACE_Task_Base *task);int suspend_task (ACE_Task_Base *task);int resume_task (ACE_Task_Base *task);int kill_task (ACE_Task_Base *task, int signum);int cancel_task (ACE_Task_Base *task, int async_cancel = 0);int hthread_within (ACE_hthread_t handle);int thread_within (ACE_thread_t tid);int num_tasks_in_group (int grp_id);int num_threads_in_task (ACE_Task_Base *task);int task_list (int grp_id, ACE_Task_Base *task_list[], size_t n);int thread_list ( ACE_Task_Base *task, ACE_thread_t thread_list[], size_t n );int hthread_list ( ACE_Task_Base *task, ACE_hthread_t hthread_list[], size_t n );int thread_grp_list ( int grp_id, ACE_thread_t thread_list[], size_t n );int hthread_grp_list ( int grp_id, ACE_hthread_t hthread_list[], size_t n );int task_all_list (ACE_Task_Base *task_list[], size_t n);int thread_all_list (ACE_thread_t thread_list[], size_t n);int set_grp (ACE_Task_Base *task, int grp_id);int get_grp (ACE_Task_Base *task, int &grp_id);int count_threads (void) const;int at_exit (ACE_At_Thread_Exit* cleanup);int at_exit (ACE_At_Thread_Exit& cleanup);int at_exit ( void *object, ACE_CLEANUP_FUNC cleanup_hook, void *param );void wait_on_exit (int dowait);int wait_on_exit (void);void dump (void);ACE_ALLOC_HOOK_DECLARE;protected:virtual int spawn_i ( ACE_THR_FUNC func, void *args, long flags, ACE_thread_t * = 0, ACE_hthread_t *t_handle = 0, long priority = ACE_DEFAULT_THREAD_PRIORITY, int grp_id = -1, void *stack = 0, size_t stack_size = 0, ACE_Task_Base *task = 0 );void run_thread_exit_hooks (int i);ACE_Thread_Descriptor *find_thread (ACE_thread_t t_id);ACE_Thread_Descriptor *find_hthread (ACE_hthread_t h_id);ACE_Thread_Descriptor *find_task ( ACE_Task_Base *task, int index = -1 );int insert_thr ( ACE_thread_t t_id, ACE_hthread_t, int grp_id = -1, long flags = 0 );int append_thr ( ACE_thread_t t_id, ACE_hthread_t, ACE_UINT32, int grp_id, ACE_Task_Base *task = 0, long flags = 0, ACE_Thread_Descriptor *td = 0 );void remove_thr (ACE_Thread_Descriptor *td, int close_handler);void remove_thr_all (void);int check_state ( ACE_UINT32 state, ACE_thread_t thread, int enable = 1 );int apply_task ( ACE_Task_Base *task, ACE_THR_MEMBER_FUNC, int = 0 );int apply_grp (int grp_id, ACE_THR_MEMBER_FUNC func, int arg = 0);int apply_all (ACE_THR_MEMBER_FUNC, int = 0);int join_thr (ACE_Thread_Descriptor *td, int = 0);int resume_thr (ACE_Thread_Descriptor *td, int = 0);int suspend_thr (ACE_Thread_Descriptor *td, int = 0);int kill_thr (ACE_Thread_Descriptor *td, int signum);int cancel_thr (ACE_Thread_Descriptor *td, int async_cancel = 0);int register_as_terminated (ACE_Thread_Descriptor *td);ACE_Double_Linked_List<ACE_Thread_Descriptor> thr_list_;ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> terminated_thr_list_;ACE_Unbounded_Queue<ACE_Thread_Descriptor*> thr_to_be_removed_;int grp_id_;int automatic_wait_;ACE_Thread_Mutex lock_;ACE_Condition_Thread_Mutex zero_cond_;private:ACE_Locked_Free_List<ACE_Thread_Descriptor, ACE_SYNCH_MUTEX> thread_desc_freelist_;static ACE_Thread_Manager *thr_mgr_;static int delete_thr_mgr_;};
Notice that if there're threads live beyond the scope of main (), you are sure to have resource leaks in your program. Remember to wait on threads before exiting main() if that could happen in your programs.
ACE_Thread_Manager (
size_t preaolloc = 0,
size_t lwm = ACE_DEFAULT_THREAD_MANAGER_LWM,
size_t inc = ACE_DEFAULT_THREAD_MANAGER_INC,
size_t hwm = ACE_DEFAULT_THREAD_MANAGER_HWM
);
virtual ~ACE_Thread_Manager (void);
static ACE_Thread_Manager *instance (void);
ACE_Thread_Manager.
static ACE_Thread_Manager *instance (ACE_Thread_Manager *);
ACE_Thread_Manager and return
existing pointer.
static void close_singleton (void);
int open (size_t size = 0);
int close ();
close_singleton, most global resources
are destroyed and thus, we don't try to wait but just clean up the thread
descriptor list.
The ACE_thread_t * argument to each of the spawn () family member functions is interpreted and used as shown in the following table. NOTE: the final option, to provide task names, is _only_ supported on VxWorks!
Value of ACE_thread_t * argument Use Platforms ================================ ========================== ========= 0 Not used. All non-0 (and points to 0 char * The task name is passed All on VxWorks) back in the char *. non-0, points to non-0 char * The char * is used as VxWorks only the task name. The argument is not modified.
int spawn (
ACE_THR_FUNC func,
void *args = 0,
long flags = THR_NEW_LWP | THR_JOINABLE,
ACE_thread_t * = 0,
ACE_hthread_t *t_handle = 0,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
int grp_id = -1,
void *stack = 0,
size_t stack_size = 0
);
func.
Returns: on success a unique group id that can be used to control
other threads added to the same group. On failure, returns -1.
int spawn_n (
size_t n,
ACE_THR_FUNC func,
void *args = 0,
long flags = THR_NEW_LWP | THR_JOINABLE,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
int grp_id = -1,
ACE_Task_Base *task = 0,
ACE_hthread_t thread_handles[] = 0,
void *stack[] = 0,
size_t stack_size[] = 0
);
func.
Returns: on success a unique group id that can be used to control
all of the threads in the same group. On failure, returns -1.
int spawn_n (
ACE_thread_t thread_ids[],
size_t n,
ACE_THR_FUNC func,
void *args,
long flags,
long priority = ACE_DEFAULT_THREAD_PRIORITY,
int grp_id = -1,
void *stack[] = 0,
size_t stack_size[] = 0,
ACE_hthread_t thread_handles[] = 0
);
func with argument arg.
If thread_ids != 0 the thread_ids of successfully spawned
threads will be placed into the thread_ids buffer (which must
be the same size as n). If stack != 0 it is assumed to be an
array of n pointers to the base of the stacks to use for the
threads being spawned. If stack_size != 0 it is assumed to be
an array of n values indicating how big each of the
corresponding stacks are. If thread_handles != 0 it is
assumed to be an array of n thread_handles that will be
assigned the values of the thread handles being spawned. Returns
-1 on failure (errno will explain...), otherwise returns the
group id of the threads.
void *exit (void *status, int do_thread_exit = 1);
do_thread_exit is
non-0 then ACE_Thread::exit is called to exit the thread, in
which case status is passed as the exit value of the thread.
Should _not_ be called by main thread.
int wait (
const ACE_Time_Value *timeout = 0,
int abandon_detached_threads = 0
);
Thread_Manager or timeout expires. Note that timeout is
treated as "absolute" time. Returns 0 on success and -1 on
failure. If abandon_detached_threads is set, wait will first
check thru its thread list for threads with THR_DETACHED or
THR_DAEMON flags set and remove these threads. Notice that
unlike other wait_* function, by default, wait () does wait on
all thread spawned by this thread_manager no matter the detached
flags are set or not unless it is called with
abandon_detached_threads flag set.
int join (ACE_thread_t tid, void **status = 0);
tid. Do not wait on a detached thread.
int wait_grp (int grp_id);
ACE_Thread_Descriptor *thread_desc_self (void);
ACE_Thread_Descriptor *thread_descriptor (ACE_thread_t);
ACE_Thread_Descriptor *hthread_descriptor (ACE_hthread_t);
int thr_self (ACE_hthread_t &);
ACE_thread_t thr_self (void);
ACE_Thread::self). However, we put it here to be complete.
ACE_Task_Base *task (void);
ACE_Task_Base we're executing
in if this thread is indeed running in an ACE_Task_Base, else
return 0.
int suspend_all (void);
int suspend (ACE_thread_t);
int suspend_grp (int grp_id);
int testsuspend (ACE_thread_t t_id);
t_id is inactive (i.e., suspended), else false.
int resume_all (void);
int resume (ACE_thread_t);
int resume_grp (int grp_id);
int testresume (ACE_thread_t t_id);
t_id is active (i.e., resumed), else false.
int kill_all (int signum);
int kill (ACE_thread_t, int signum);
int kill_grp (int grp_id, int signum);
int cancel_all (int async_cancel = 0);
int cancel (ACE_thread_t, int async_cancel = 0);
int cancel_grp (int grp_id, int async_cancel = 0);
int testcancel (ACE_thread_t t_id);
t_id is cancelled, else false.
int set_grp (ACE_thread_t, int grp_id);
int get_grp (ACE_thread_t, int &grp_id);
ACE_Thread Manager. For example, the apply_task
method resembles the apply_thr method, and suspend_task
resembles suspend_thr.
int wait_task (ACE_Task_Base *task);
task. Returns
0 on success and -1 on failure. Notice that wait_task will not
wait on detached threads.
int suspend_task (ACE_Task_Base *task);
int resume_task (ACE_Task_Base *task);
int kill_task (ACE_Task_Base *task, int signum);
signum to all threads in an ACE_Task.
int cancel_task (ACE_Task_Base *task, int async_cancel = 0);
ACE_Task. If async_cancel is non-0,
then asynchronously cancel these threads if the OS platform
supports cancellation. Otherwise, perform a "cooperative"
cancellation.
int hthread_within (ACE_hthread_t handle);
int thread_within (ACE_thread_t tid);
int num_tasks_in_group (int grp_id);
ACE_Task_Base in a group.
int num_threads_in_task (ACE_Task_Base *task);
ACE_Task_Base.
int task_list (int grp_id, ACE_Task_Base *task_list[], size_t n);
task_list a list of up to n ACE_Tasks in a
group. The caller must allocate the memory for task_list. In
case of an error, -1 is returned. If no requested values are
found, 0 is returned, otherwise correct number of retrieved
values are returned.
int thread_list (
ACE_Task_Base *task,
ACE_thread_t thread_list[],
size_t n
);
thread_list a list of up to n thread ids in an
ACE_Task_Base. The caller must allocate the memory for
thread_list. In case of an error, -1 is returned. If no
requested values are found, 0 is returned, otherwise correct
number of retrieved values are returned.
int hthread_list (
ACE_Task_Base *task,
ACE_hthread_t hthread_list[],
size_t n
);
hthread_list a list of up to n thread handles in
an ACE_Task_Base. The caller must allocate memory for
hthread_list. In case of an error, -1 is returned. If no
requested values are found, 0 is returned, otherwise correct
number of retrieved values are returned.
int thread_grp_list (
int grp_id,
ACE_thread_t thread_list[],
size_t n
);
thread_list a list of up to n thread ids in a
group grp_id. The caller must allocate the memory for
thread_list. In case of an error, -1 is returned. If no
requested values are found, 0 is returned, otherwise correct
number of retrieved values are returned.
int hthread_grp_list (
int grp_id,
ACE_hthread_t hthread_list[],
size_t n
);
hthread_list a list of up to n thread handles in
a group grp_id. The caller must allocate memory for
hthread_list.
int task_all_list (ACE_Task_Base *task_list[], size_t n);
task_list a list of up to n ACE_Tasks. The
caller must allocate the memory for task_list. In case of an
error, -1 is returned. If no requested values are found, 0 is
returned, otherwise correct number of retrieved values are
returned.
int thread_all_list (ACE_thread_t thread_list[], size_t n);
thread_list a list of up to n thread ids. The
caller must allocate the memory for thread_list. In case of an
error, -1 is returned. If no requested values are found, 0 is
returned, otherwise correct number of retrieved values are
returned.
int set_grp (ACE_Task_Base *task, int grp_id);
int get_grp (ACE_Task_Base *task, int &grp_id);
int count_threads (void) const;
Thread_Manager.
int at_exit (ACE_At_Thread_Exit* cleanup);
int at_exit (ACE_At_Thread_Exit& cleanup);
int at_exit (
void *object,
ACE_CLEANUP_FUNC cleanup_hook,
void *param
);
Register an object (or array) for cleanup at
thread termination. "cleanup_hook" points to a (global, or
static member) function that is called for the object or array
when it to be destroyed. It may perform any necessary cleanup
specific for that object or its class. "param" is passed as the
second parameter to the "cleanup_hook" function; the first
parameter is the object (or array) to be destroyed.
"cleanup_hook", for example, may delete the object (or array).
If cleanup_hook == 0, the object will _NOT_ get cleanup at
thread exit. You can use this to cancel the previously added
at_exit.
void wait_on_exit (int dowait);
int wait_on_exit (void);
void dump (void);
ACE_ALLOC_HOOK_DECLARE;
int check_state (
ACE_UINT32 state,
ACE_thread_t thread,
int enable = 1
);
thread is in a particular state.
This call updates the TSS cache if possible to speed up
subsequent searches.
int apply_task (ACE_Task_Base *task, ACE_THR_MEMBER_FUNC, int = 0);
func to all members of the table that match the task
int apply_grp (int grp_id, ACE_THR_MEMBER_FUNC func, int arg = 0);
func to all members of the table that match the grp_id.
int apply_all (ACE_THR_MEMBER_FUNC, int = 0);
func to all members of the table.
int join_thr (ACE_Thread_Descriptor *td, int = 0);
tda.
int resume_thr (ACE_Thread_Descriptor *td, int = 0);
tda.
int suspend_thr (ACE_Thread_Descriptor *td, int = 0);
tda.
int kill_thr (ACE_Thread_Descriptor *td, int signum);
signum to the thread described in tda.
int cancel_thr (ACE_Thread_Descriptor *td, int async_cancel = 0);
tda.
int register_as_terminated (ACE_Thread_Descriptor *td);
terminated_thr_list_.
ACE_Double_Linked_List<ACE_Thread_Descriptor> thr_list_;
ACE_Double_Linked_List<ACE_Thread_Descriptor_Base> terminated_thr_list_;
ACE_Unbounded_Queue<ACE_Thread_Descriptor*> thr_to_be_removed_;
int grp_id_;
int automatic_wait_;
ACE_Thread_Mutex lock_;
zero_cond_.
ACE_Condition_Thread_Mutex zero_cond_;