[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[IMP-dev] Last week in IMP



Changes for the week:

    * FilteredListSingletonContainer and
FilteredPairSingletonContainer went away as there was too much hard to
factor code shared with ListSingletonContainer and
PairSingletonContainer. The IMP::core::ClosePairsScoreState is now
handled by a list of filters on the class itself. That is, do
IMP::core::ClosePairsScoreState::add_close_pair_filter() to add a
filter.

    * Hooks have been added to allow actions to be taken on an
assertion or check failure. See IMP::HandleFailure and its descendents
for more details. For exampe, one can write out the model to a file to
view in chimera on each error.

    * IMP::display::CGOWriter has been much improved and now allows
provides lots of display-time control and easy building of animations.

    * Generic optimizer states have been added
(IMP::core::SingletonsOptimizerState and
IMP::core::PairsOptimizerState).


We have a choice for the IMP-dev meeting next week:
(1) how to use the various error checking macros and functions in your
own code (IMP_check, IMP_assert, failure handlers)
(2) an overview of the tools available for manipulating molecules:
What we have, what we need.
Sends preferences to me.

Since a few questions have come up about it, I thought I would say a
few words about why we use reference counted pointers and why, in
general, no classes should ever store raw pointers to other objects.

All entities in a compute program have lifetimes, that is, the
interval between when they are created to when they are destroyed.
Once an object's lifetime is over, it is an error to access the
object. In C++ programs, the lifetime of a local variable is that of
the scope containing them (they are alive, for example, until the
function in which they are defined exits). The lifetime of objects
created using "new" lasts until "delete" is called on them.

On important question in any computer system is how the lifetime of
shared objects is managed. A shared object is one that is accessed via
stored pointers or references from a variety of places. It is
exacerbated in IMP, since any object that python sees is implicitly
shared with python, and python will delete any object it thinks is no
longer in use. There are several common conventions for dealing with
shared objects:

(1) the code which created the shared object is responsible for
destroying it. This convention shifts all the load to the users since,
the user needs to know when all other code is done with the shared
object and explicitly keep it alive until then. As a result, this
convention only works with small systems where someone can understand
all the internal relationships between objects.

(2) eliminate shared objects. Nice and simple, but quite limiting.

(3) reference counting: With reference counting, shared objects are
kept alive until everything is done with them. This is typically done
by associating a reference count with each object. Each bit of code
using the shared object increments the counter when it acquires a
reference to the object and then decrements the counted when it is
done. When the counter goes to zero, nothing is using the object and
the object can go away.

(4) garbage collection: a garbage collector scans the running program
to determine when the object no longer in used and then deletes it.
This is what java does, but is very hard to implement in C++


In IMP we chose (3), both because it is what Python does and is
relatively straight foward. To make your life easier, objects in IMP
are divided into little-o-objects which should never be shared and
big-O objects which should be passed by pointers and can be shared. It
also provides a class, IMP::Pointer to handle the incrementing and
decrementing of the reference count for you. To make sure an object
doesn't go away, just create an reference counted pointer with
IMP::Pointer<ObjectType> my_object_ref_counted_pointer(my_object_ptr);
This increments the reference count. When
my_object_ref_counted_pointer is destroyed, the reference count will
be decremented, relinquishing control of the object. The reference
counts are shared with Python, so an object will not be deleted until
python is done with it and all there are no reference counted pointers
referring to it. It is also quite easy to define your own reference
counted object: simply inherit from IMP::RefCounted. Collections of
reference counted objects can be stored using an
IMP::VectorOfRefCounted (Particles, Restraints etc use this
mechanism).