|
Boost Users : |
From: Bruno Martínez (br1_at_[hidden])
Date: 2006-09-17 13:44:15
On Fri, 15 Sep 2006 11:16:21 -0300, Robert Kindred <RKindred_at_[hidden]>
wrote:
> I can think of one example for not fully constructing objects:
>
> I've got some multi-threaded programs where I have found that it is quite
> convenient for each of my threads to be a C++ object. The private thread
> variables are C++ private data members. These threads cooperate with one
> another by sending messages to each other through locking message queues.
> In this way private data members do not need to be locked, as each
> message
> is processed sequentially.
>
> The problem is in starting up. If each one of these threads knows about
> each other via some method (pointer, or reference), then when a thread
> starts up its own business, whatever that is, then most likely it will
> start
> generating data and sending messages. When it tries to send a message
> to a
> thread that does not yet exist, BOOM!!! (yes, I have experienced this
> boom).
>
> My solution to this is not to start the threads running in the
> constructor.
> I can create all of the thread objects in any order I like, then I can
> start
> them running as threads in any order that I like, through a member
> function
> call to each one. If a thread sends a message to another thread object
> not
> yet running, then the message simply waits in his queue, until he wakes
> up
> and begins processing messages.
>
> Consequently, at program shutdown time, one cannot just start deleting
> thread objects. If you were to delete a thread object that other thread
> objects are messaging, BOOM!! (or as they say in this newsgroup,
> undefined
> behavior). My answer to this is to signal each thread to come to a stop
> on
> its own accord. Once all threads are stopped, then they can be deleted
> in
> any order. So, I don't have monolithic destructors, either.
>
> Of course, you may consider a thread object that is not yet running is
> actually fully constructed. I am not sure of the definition.
I find this situation sometimes too. My solution follows Stroustrup's
advice. When I can't break a cycle I create an entity that stands for the
collection of interrelated instances/classes. In your example each thread
object maintains an invariant, but the collection of threads have a
stronger invariant than the sum of invariants. That can be seen in that
both construction and destruction require special care.
In Haskell some cases of two phase construction can be avoided because of
it's lazy nature. You can have references to objects that still don't
exist, without having destructive assignments. It really rocks:
http://www.haskell.org/hawiki/TyingTheKnot
Bruno
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net