Hi Andrewas,
Thanks for using the PRF.
>> ACE VERSION: 5.2.1
>> HOST MACHINE and OPERATING SYSTEM: Intel P4, Win2k professional
>> TARGET MACHINE and OPERATING SYSTEM, if different from HOST:
>> COMPILER NAME AND VERSION (AND PATCHLEVEL): BCB 5 ( Compiler: bcc32.exe
>> Version 5.5 )
>> AREA/CLASS/EXAMPLE AFFECTED: ACE_Task
>> DOES THE PROBLEM AFFECT: EXECUTION Application is affected
>> SYNOPSIS:
>> Thread of dynamically generated ACE_Task object is not shut down, if
>> "delete this;" is done within close().
>> DESCRIPTION:
>> If have a ACE_Task called "kernel" processing messages. If a calculation
>> request comes in the kernel
>> generates dynamically a ACE_Task derived object (CalcTask) , which does
>> the calculation. The CalcTask
>> sends back to the kernel the result via a message. At this point the
>> CalcTask can be deleted. There are two ways:
>> 1. Kernel deletes the Task
>> This is basically:
>> calcTask=new
>> ClaDisCalcTask(calcTaskID,this,datain->clientTask,code,TheCounterObject,pFi l
>> ter, pRunParam,Item);
>> calcTask->open(0);
>> ....
>> ....
>> calcTask->msg_queue()->deactivate ();
>> calcTask->wait (); // Wait for the thread to exit.
>> delete calcTask; // Reclaim the task memory.
>> 2. Task deletes itself
>> This is basically:
>> _KERNEL_:
>> calcTask=new
>> ClaDisCalcTask(calcTaskID,this,datain->clientTask,code,TheCounterObject,pFi l
>> ter, pRunParam,Item);
>> calcTask->open(0);
>> _CALCTASK_:
>> int ClaDisCalcTask::close(u_long)
>> {
>> msg_queue()->deactivate ();
>> delete this;
>> }
>> The first solution (1) works fine. The generated thread is really destroyed
>> ( according to system monitoring tools ).
>> But I would prefer the second solution, because it is more stable, as the
>> kernel never has to wait() for the task.
>> The second solution(2) doesn't work fine, as the thread still exists.
>> What is the exact solution, to have a task delete itself and really destroy
>> the generated thread ??
This topic is discussed in depth in C++NPv2
<
www.cs.wustl.edu/~schmidt/ACE/book2/>. Since the book won't be published
until the fall, however, I've enclosed the sidebar that explains
what to do:
----------------------------------------
Sidebar X: Destroying an ACE_Task
Special care must be taken when destroying an ACE_Task that runs as an
active object. Before destroying this object, you must ensure that
the thread(s) running its svc() method have exited. Page Y describes
several techniques to shutdown svc() methods that are blocked on a
task's message queue. One way to ensure a proper destruction sequence
looks like this:
My_Task *task = new Task; // Allocate a new task dynamically.
task->open (); // Initialize the task.
task->activate (); // Activate task to run as an active object.
// ... do work ...
// Deactive the message queue so that the svc() method unblocks
// and the thread exits. task->close () will be called
// automatically when the thread exits.
task->msg_queue ()->deactivate ();
task->wait (); // Wait for the thread to exit.
delete task; // Reclaim the task memory.
Similar logic can be used if the task is allocated on the run-time
stack.
If a task is allocated dynamically, a better approach may be to have
the task's close() hook delete itself when a thread exits, rather than
calling delete on a pointer to the task directly. You may still want
to wait() on the threads to exit the task, however, particularly if
you're preparing to shutdown the process. On some OS platforms, when
the main thread returns from the main() the entire process will be
shut down immediately, whether there were other threads active or not.
----------------------------------------
Take care,
Doug
--
Dr. Douglas C. Schmidt, Associate Professor TEL: (949) 824-1901
Dept of Electrical & Computer Engineering FAX: (949) 824-2321
616E Engineering Tower WEB: www.ece.uci.edu/~schmidt/
University of California, Irvine, 92697-2625 NET: schm...@uci.edu