|
Boost Users : |
From: Jason Winnebeck (yg-boost-users_at_[hidden])
Date: 2003-07-17 10:39:51
Peter Dimov wrote:
> Jason Winnebeck wrote:
> There are no inherent cycles so far in the design. A typical Listener
> interface is
>
> struct Listener
> {
> virtual void accept(Event const & event, Generator & sender) = 0;
> };
>
> so that it can listen to several Generators at a time. The assumption is
> that Listener::accept cannot destroy 'sender'.
Hmm yes I do like that interface. For some reason when I designed my
API over 2 years ago I didn't think to pass the generator into the
event. I expected that the listener would hold a strong pointer to its
generator anyway. Since I'm breaking backwards compatibility anyway for
a redesign, one could argue now is the time to break it more, but I
think breaking less is better than breaking more...
I would be pretty warm to it, but I want to first hear how you would
design the user code. I thought it was very convinent to set a listener
and just go about ignoring it forever if you want. If you were to say
to just simply create a list of listeners you never access or care about
in some list simply to keep them alive, removing listeners when their
connections died (you would also have to keep a list of all connections
and scan them constantly to check for dead connections), then you have
just ended up implementing a garbage collection scheme, and one would
have to ask why use shared_ptr to begin with when you have to contain
lists of every object in your program and scan them for unused objects.
I wanted to move the API to use shared_ptr for that explicit reason so
that the user doesn't have to maintain lists of every object they create
checking for object death.
> Logically, if a Generator does not own its Listeners, it should keep weak
> pointers. The advantage is that dead Listeners that haven't unregistered can
> be auto-unsubscribed by the Generator (unless you have real measurements
> that indicate a performance problem with weak_ptr::lock(), which would
> surprise me :-).)
It makes real sense when you say it that way. Although my generator
classes only allow for a single listener (perhaps a bad idea), but I
have thought about changing this, or providing a listener that has a
list of listeners it distributes across (an adaptor of sorts). I could
implement both the single listener/not passing generator reference
scheme, and provide an adaptor class that allows for multiple listeners
and passing in a reference to the event source, but as said before,
adding complexity like that to the API is generally bad.
I am curious about the overhead for weak_ptr's lock. Looking at the
code you have to do the normal mutex lock then a try/catch and construct
a new shared_ptr and so forth. It's the synchronization cost that I'm
unsure about but I would think that the code might be a little
expensive? I would say events are occuring constantly, but events
occuring every 10-100ms is not constant by any means to a computer, and
certainly not a "tight loop" subject to optimization.
Thank you for your time,
Jason
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