
-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org]On Behalf Of Matthew Vogt Sent: Tuesday, February 24, 2004 12:06 PM To: boost@lists.boost.org Subject: [boost] Re: [Threads] Simple active object wrapper, take 2
scott <scottw <at> qbik.com> writes:
Well, ok. Futures (in my code, and in the pattern) do allow a caller to access a result asynchronously, if you define asynchronously to mean that the caller is free to pursue other interests before acquiring the result.
What is lacking is the ability to multiplex over events relating to the delivery of future values. You can't use select, poll or WFMO to determine whether any of an outstanding set of futures have been delivered. I think that this probably makes active objects an inappropriate choice for designs that are inherently reactive.
Yes, exactly. Is there no potential to leverage the mechanism you already have, i.e. "task"? It seems almost tragic that you have such a slick method of delivering "Method Requests" and that it cant be used to deliver "Method Results" asynchronously. In another implementation this just involved storing some kind of "return address" and adding that to the queued object (task). On actual execution the thread (belonging to the active object) need only turn around and write the results back into the callers queue. This all assumes that we are discussing symmetric activation. And even want to go there :-)
You could apply the active object pattern to this design, but the simplest way to do so would be to constrain the slave threads to have void-returning
<snip>
(I think this is a variant on the 'half-sync, half-asynch' pattern?)
Ideally, though, the server is a reactive design and not terribly suited to the active object pattern.
<snip>
Well, yes, you could (and it could certainly be generic, I'm sure). But it doesn't seem to be in the spirit of the design. Active object is a trade-off between simplicity at the client, and suboptimal performance at the server.
<snip>
This is certainly achievable, but is it using the active object design? You can implement an exactly equivalent design using the platform AIO primitives, but this would yield code which was much harder to follow and implement than active objects communicating through function calls. If you want optimum throughput throughout the interracting components, I don't think active object is the pattern you're looking for.
<snip> I included the last few fragments of your message to give myself an opportunity to review them as a group. Yes, I understood most of your points. Some of the confusion or gray areas in our exchange have been due to the mis-application (mine) of the ActiveObject pattern. The ActiveObject pattern was introduced early on and became a convenient vocabulary and point of reference. In truth it was never my target (I hadnt seen it previous to our discussion). It is totally impressive work but does duck a major nasty. So, to hopefully clarify; I still feel there is a software abstraction that we (as developers) intuitively want. It is not completely delivered by the ActiveObject pattern (though I thank JG again for the reference). As mentioned in my previous message the pattern has no mechanism for asynchronous return of results. This is a source of wonderment (tending towards frustration) as (IMHO) this is the Missing Link. The frustration stems from the fact that all the machinery is inherently available having previously implemented the delivery of "Method Requests". Just "turn it around" and let the completing method deliver the results to the original caller :-)
The asynchronous delivery mechanism is the conversion of the 'future' template object to it's parameterised type. For example, the following blocks:
future<int> f = someActiveObject.someMethod(); // Non-blocking int i = f; // Blocks until result delivered
Of course, the caller may not need the result yet, and can postpone the wait indefinitely:
As I see it, futures is the closest that the asymmetric activation can get to "async-res". But it isnt close enough. When I refer to asyn-res I am typically referring to the delivery of results from one active object to another, where the receiving object is not required to enter into a (potentially) blocking call (e.g. evaluation of a future). I have tried to label this circumstance as "symmetric activation". This can only occur between two active objects <cringe>. Perhaps we could leave behind the "active object" term and go for "reactive object"? Perhaps you now own the "active object" name and the abstraction that I continue to rave about, lays claim to "reactive object"?
It might be interesting to note that my ActiveWorld implementation is _completely_ SA. The very pleasant surprise for me has been the successful manner in which it has been deployed in existing codebases. It may appear foreign but our best coding is naturally trying to emulate the SA ActiveObject.
What interface are you using to allow active objects to access results generated by other active objects?
The short answer is; the same interface used to deliver Method Requests. The long answer would definitely be long. I can post some code fragments if we are still swimming after the same stick?
methods
of that same struct and those methods are only every called by "boost::thread thread" in "class active". Voila! We dont need any mutexes around that data!
Yes, but that only applies to a single-threaded active object.
<sigh, lowers shoulders> ;-) In my ActiveWorld, no active object has more than a single thread. They are either no thread (i.e. servants) or single-thread (a scheduler deriving from the servant interface). Where an active object deploys "slave threads", these are also zero or one thread, i.e. they are also active objects. This may sound unnecessarily convoluted but this small object hierarchy provides the basis for building arbitrary hierarchies of threads. If that is what you want :-) The big plus being that there is only the one mechansim being used for inter-thread communication. Within this object hierarchy and threading model (that I am making such a meal of) any data declared with private scope in "struct object" is thread-safe. Yes, because there is only ever the one thread :-) Its been fun up to this point but perhaps your "code with legs" is viable as "active object" and that is a valid first phase? I could wheel my barrow off to the side for a while :-) Cheers, Scott