|
Boost : |
Subject: Re: [boost] [msm] Message queue and copy constructed events
From: Richard Szabo (sz.richard_at_[hidden])
Date: 2010-06-22 08:12:09
On 22 June 2010 11:47, Christophe Henry
<christophe.j.henry_at_[hidden]> wrote:
> Hi Richard,
>
>>Lets separate 2 thinks.
>>
>>1: no heap operation this is a nice to have feature we can live with
>>it. According my understanding the only place where heap is used is in
>>the std:queue ? Am I correct ? If yes than if the user has a
>>possibility to provide its own queue implementation than he/she can
>>make sure about avoiding heap usage.
>
> In the queue AND in the boost::function objects contained in the
> queue. So merely changing the container will not be sufficient to
> eliminate all heap usage (read further on).
>
>>2: event copying. You saying copy is happening when bind is used to
>>anonymize events to be able to store them in a queue.
>>According my understanding of event driven systems we can say that as
>>log an RTC step is not finished -> means that the most outer
>>process_event does not retuned the event which was used in the call of
>>the process_event should be valid. This means that events will be
>>valid even with queuing for queues which are used during pseudo entry
>>and exit because the processing of those events are always finished
>>before the more outer process_event is returned.
> >The only place where this is not true ->when the event should be
>>available longer than the RTC step is when the event is deferred.
>>So I think it would be enough for non deferred queues to internally
>>before the bind store the event in a ref/cref and bind that and put
>>to the queue -> no copy.
>
> This is incorrect. You can have the same behaviour with the event
> queue. Consider test/SimpleWithFunctors.cpp:
> You have a transition:
> Row < Empty , cd_detected , Stopped , store_cd_info , ... >
>
> And in the action, we generate another event:
>
> struct store_cd_info
> {
> template <class EVT,class FSM,class SourceState,class TargetState>
> void operator()(EVT const&,FSM& fsm ,SourceState& ,TargetState& )
> {
> fsm.process_event(play()); // temporary play will be
> queued, then the function returns
> // ooops, temporary is gone
> }
> /// end of action, transition now ends and will start examining
> the queue and will find inside a reference to a destroyed event
> };
>
> Now, if msm was using ref/cref, we would be processing a destroyed
> event, which would not end well ;-)
>
> Unfortunately, it is not possible for process_event to know if the
> event object is a temporary, therefore the copy. The only way to
> change this would be to have the user tell msm about it and take
> responsibility for ensuring event validity. We could:
> - have an extra parameter to process_event (run-time cost for all users)
> - allow some compile-time flag (compile-time cost for all users)
>
> None is very appealing to me as I doubt many will require this,
> especially as I fail to see why you could not pimpl the event data,
> thus making the event cheap to copy. But everybody would have to pay
> for it somehow. And the heap issue would still be unsolved.
> This would likely also end at the very bottom of my feature list.
>
> I think a possible solution would be the fact that I intend to offer
> customization of the queue container, which is a much more popular
> feature. Instead of calling push on it with the boost::function
> object, I could call push(event), so that you can provide a container
> not of function objects but of anything (like of a pointers to some
> base event type or void* if you prefer to cast a little, which I
> prefer not knowing of ;-) ).
> This allows complete removal of any heap usage AND could also be used
> to get rid of event copying (in this case though, you are taking
> responsibility of having thought of the event objects' lifetime). The
> downside is that providing a new container will require slightly more
> work.
Thanks for the example all make sense.
push with an event and a recall would be sufficient for us.
That we can integrate with our non copy event queues and event factories.
>
>>For deferred queues there is 2 ways to go.
>>First is to copy the event during bind or have a user implement a
>>queue which interacts whit the underlaying zero copy scheduler. and
>>only again store a ref/cref in a bind. maybe it is enough to have 2
>>callback to the user when an event is deferred and when it is recalled
>>and not needed any more.
>
> Fore the deferred queue, I can provide the same mechanism, so that you
> have have different containers for both if you wish.
> Using boost.parameter will make these extra template arguments more bearable.
>
It can be a different definition as the normal event queue and if it
is the same handling as normal event queue
than the user can put the same underlying implementation.
>
> Regards,
>
> Christophe
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
>
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk