knowledge-database (beta)

Current group: comp.soft-sys.ace

[ace-users] ACE_Module is not polymorphic (and should be!)

[ace-users] ACE_Module is not polymorphic (and should be!)  
David Hawkins
From:David Hawkins
Subject:[ace-users] ACE_Module is not polymorphic (and should be!)
Date:22 Jan 2005 22:59:35 -0600

Hi all,

Yep, I'm still working on Streams :)

There is another problem with the C++NPv2 p302
example. The example inherits from ACE_Module<>,
and then the modules are inserted into a stream
via their base-class pointers. i.e., they're
being used polymorphically.

However, ACE_Module<>'s destructor is NOT virtual,
so any derived object destructor will not be called.
This means that the task_ member of that class
will 'leak', i.e., never be destroyed.

The examples in APG, Chapter 18, p381 use a

typedef ACE_Module Module;

and then call the ACE_Module constructor directly,
i.e., they do not use inheritance. So that form
of example would work fine.

Later the CommandModule is defined on p402 and
that does inherit from ACE_Module<>. However, in
that case the inherited class does not define
any member variables, it just modifies the
constructor interface and introduces a new
function that internally casts the argument
contained within the underlying base class.
So, there would be no problems with this
type of inheritance.

However, its particularly misleading as both
examples suggest that inheriting from ACE_Module
is one of the intended uses of this class.

The C++NPv2 example could use inheritance in
the same way as the APG, however, the template for
the class would instead need to dynamically allocate
the task in the constructor body, and then pass
that task down to the module baseclass and set
the appropriate delete flag. This scheme replaces
the constructor with the shortened version (fewer
arguments), and does not introduce any new member
variables, so the fact that the derived destructor
is not called does not leak. However, its disconcerting
if you have a trace/debug statement in your
destructor and it never gets called!

Making the ACE_Module destructor virtual seems
like a cleaner solution!

An example of the issue:

http://www.ovro.caltech.edu/~dwh/ace/ace_module_not_virtual.cpp

http://www.ovro.caltech.edu/~dwh/ace/ace_module_not_virtual.txt

----------------------------------------
Main: Stack module object
Task: constructor
Task: constructor
Module: constructor
Module: destructor
Task: destructor
Task: destructor
----------------------------------------
Main: Dynamic module object assigned
to a pointer of the same type
Task: constructor
Task: constructor
Module: constructor

Main: Delete it
Module: destructor
Task: destructor
Task: destructor
----------------------------------------
Main: Dynamic module object assigned
to a pointer of the base type
Task: constructor
Task: constructor
Module: constructor

Main: Delete it


The example creates a stack object, and you can see its
contents destruct when it goes out of scope. Similarly
when a dynamically allocated module is assigned to a
pointer of its type, and then that object is deleted,
it also destructs. However, when the dynamically allocated
module is assigned to a base class pointer (ACE_Module)
the call to delete only deletes the base-class ... oops
resource leak.

Since the Streams interface uses pointers to ACE_Modules<>,
and it is responsible for DELETING them, the class
passed in either has to BE an ACE_Module, or has
to derive polymorphically from ACE_Module
(which it can't, since the destructor is not
virtual).

Why does this matter? Well, I see the whole point
of the streams interface as being able to create
a whole suite of pre-canned modules, that I can
then plug together to create different applications:

eg. producer consumer
-------- --------
Simulator FileWriter
Hardware Server
Client

So I can plug a similator into a filewriter and generate
a set of test data (CDR-encoded), I can then take it
into MATLAB and plot it. Then I change the simulator
for real hardware, write the data to file, and check it.
Then I plug the hardware into a server, and a client into
a filewriter and I check I can send data across the network
and read it ok. Then I plug multiple sets of hardware
into multiple servers, and then create multiple
clients that collect all that data and pipe it to
either a filewriter or another server. This small
set of modules can generate a whole suite of
applications. I'm trying to save myself some
code maintenance here! :)

The hardware is an array of radio telescopes:

http://www.ovro.caltech.edu/~dwh/correlator/


Cheers
Dave Hawkins
Caltech.
   

Copyright © 2006 knowledge-database   -   All rights reserved