DRTVWR-474: Make LLEventMailDrop pass all saved events to listener.
Previously, LLEventMailDrop would send only the first queued event to a newly-connected listener. If you wanted to flush all queued events, you'd have to "pump" the queue by repeatedly disconnecting and reconnecting -- with no good way to know when you'd caught up. The new behavior makes LLEventMailDrop resemble a multi-valued future: a rendezvous between producer and consumer that, once connected, pushes values rather than requiring them to be pulled (as with a simple queue) -- regardless of the relative order in which post() and listen() are called.master
parent
e1826d508c
commit
ec6487f3a7
|
|
@ -545,10 +545,8 @@ bool LLEventStream::post(const LLSD& event)
|
|||
*****************************************************************************/
|
||||
bool LLEventMailDrop::post(const LLSD& event)
|
||||
{
|
||||
bool posted = false;
|
||||
|
||||
if (!mSignal->empty())
|
||||
posted = LLEventStream::post(event);
|
||||
// forward the call to our base class
|
||||
bool posted = LLEventStream::post(event);
|
||||
|
||||
if (!posted)
|
||||
{ // if the event was not handled we will save it for later so that it can
|
||||
|
|
@ -564,16 +562,25 @@ LLBoundListener LLEventMailDrop::listen_impl(const std::string& name,
|
|||
const NameList& after,
|
||||
const NameList& before)
|
||||
{
|
||||
if (!mEventHistory.empty())
|
||||
// Before actually connecting this listener for subsequent post() calls,
|
||||
// first feed each of the saved events, in order, to the new listener.
|
||||
// Remove any that this listener consumes -- Effective STL, Item 9.
|
||||
for (auto hi(mEventHistory.begin()), hend(mEventHistory.end()); hi != hend; )
|
||||
{
|
||||
if (listener(mEventHistory.front()))
|
||||
if (listener(*hi))
|
||||
{
|
||||
mEventHistory.pop_front();
|
||||
// new listener consumed this event, erase it
|
||||
hi = mEventHistory.erase(hi);
|
||||
}
|
||||
else
|
||||
{
|
||||
// listener did not consume this event, just move along
|
||||
++hi;
|
||||
}
|
||||
}
|
||||
|
||||
// let base class perform the actual connection
|
||||
return LLEventStream::listen_impl(name, listener, after, before);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -650,15 +650,21 @@ public:
|
|||
* LLEventMailDrop
|
||||
*****************************************************************************/
|
||||
/**
|
||||
* LLEventMailDrop is a specialization of LLEventStream. Events are posted normally,
|
||||
* however if no listeners return that they have handled the event it is placed in
|
||||
* a queue. Subsequent attaching listeners will receive stored events from the queue
|
||||
* until a listener indicates that the event has been handled. In order to receive
|
||||
* multiple events from a mail drop the listener must disconnect and reconnect.
|
||||
* LLEventMailDrop is a specialization of LLEventStream. Events are posted
|
||||
* normally, however if no listener returns that it has handled the event
|
||||
* (returns true), it is placed in a queue. Subsequent attaching listeners
|
||||
* will receive stored events from the queue until some listener indicates
|
||||
* that the event has been handled.
|
||||
*
|
||||
* LLEventMailDrop completely decouples the timing of post() calls from
|
||||
* listen() calls: every event posted to an LLEventMailDrop is eventually seen
|
||||
* by all listeners, until some listener consumes it. The caveat is that each
|
||||
* event *must* eventually reach a listener that will consume it, else the
|
||||
* queue will grow to arbitrary length.
|
||||
*
|
||||
* @NOTE: When using an LLEventMailDrop (or LLEventQueue) with a LLEventTimeout or
|
||||
* LLEventFilter attaching the filter downstream using Timeout's constructor will
|
||||
* cause the MailDrop to discharge any of it's stored events. The timeout should
|
||||
* LLEventFilter attaching the filter downstream, using Timeout's constructor will
|
||||
* cause the MailDrop to discharge any of its stored events. The timeout should
|
||||
* instead be connected upstream using its listen() method.
|
||||
* See llcoro::suspendUntilEventOnWithTimeout() for an example.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Reference in New Issue