initial implementation
This commit is contained in:
parent
43a08a9628
commit
0157f8dc04
12 changed files with 703 additions and 658 deletions
|
|
@ -7,124 +7,124 @@
|
|||
#include <cstdint>
|
||||
|
||||
namespace xo {
|
||||
namespace reactor {
|
||||
class Reactor;
|
||||
namespace reactor {
|
||||
class Reactor;
|
||||
|
||||
/* abstract api for a source of events.
|
||||
* Event representation is left open: Sources and Sinks
|
||||
* need to have compatible event representations,
|
||||
* and coordination is left to such (Source, Sink) pairs.
|
||||
*
|
||||
* Source->Sink activity may be expected to be mediated by a reactor,
|
||||
* that implements the Reactor api.
|
||||
*
|
||||
* At any time, A Source can be associated with at most one reactor.
|
||||
* Sources are informed of Reactor<->Source association being
|
||||
* formed/broken by the
|
||||
* .notify_reactor_add(), .notify_reactor_remove()
|
||||
* methods
|
||||
*
|
||||
* The source api intends also to provide for simulation.
|
||||
* There introduces two simulation-specific methods:
|
||||
* .sim_current_tm()
|
||||
* .sim_advance_until()
|
||||
*
|
||||
* A non-simulation source can implement these as calls to
|
||||
* .online_current_tm(), .online_advance_until() respectively
|
||||
* .online_current_tm() aborts since an online source is never exhausted
|
||||
* .online_advance_until() is a no-op that returns 0
|
||||
*
|
||||
* Loop for consuming from a primary simulation source:
|
||||
*
|
||||
* brw<Source> s = ...;
|
||||
* while(!s->is_exhausted())
|
||||
* s->deliver_one();
|
||||
*
|
||||
* Secondary sources (sources that depend on other sources) can be
|
||||
* in a state where they don't know their next event, in which case:
|
||||
*
|
||||
* s->is_notprimed() == true
|
||||
*/
|
||||
class ReactorSource : public AbstractSource {
|
||||
public:
|
||||
using utc_nanos = xo::time::utc_nanos;
|
||||
/* abstract api for a source of events.
|
||||
* Event representation is left open: Sources and Sinks
|
||||
* need to have compatible event representations,
|
||||
* and coordination is left to such (Source, Sink) pairs.
|
||||
*
|
||||
* Source->Sink activity may be expected to be mediated by a reactor,
|
||||
* that implements the Reactor api.
|
||||
*
|
||||
* At any time, A Source can be associated with at most one reactor.
|
||||
* Sources are informed of Reactor<->Source association being
|
||||
* formed/broken by the
|
||||
* .notify_reactor_add(), .notify_reactor_remove()
|
||||
* methods
|
||||
*
|
||||
* The source api intends also to provide for simulation.
|
||||
* There introduces two simulation-specific methods:
|
||||
* .sim_current_tm()
|
||||
* .sim_advance_until()
|
||||
*
|
||||
* A non-simulation source can implement these as calls to
|
||||
* .online_current_tm(), .online_advance_until() respectively
|
||||
* .online_current_tm() aborts since an online source is never exhausted
|
||||
* .online_advance_until() is a no-op that returns 0
|
||||
*
|
||||
* Loop for consuming from a primary simulation source:
|
||||
*
|
||||
* brw<Source> s = ...;
|
||||
* while(!s->is_exhausted())
|
||||
* s->deliver_one();
|
||||
*
|
||||
* Secondary sources (sources that depend on other sources) can be
|
||||
* in a state where they don't know their next event, in which case:
|
||||
*
|
||||
* s->is_notprimed() == true
|
||||
*/
|
||||
class ReactorSource : public AbstractSource {
|
||||
public:
|
||||
using utc_nanos = xo::time::utc_nanos;
|
||||
|
||||
public:
|
||||
virtual ~ReactorSource() = default;
|
||||
public:
|
||||
virtual ~ReactorSource() = default;
|
||||
|
||||
/* true if source is currently empty (has 0 events to deliver) */
|
||||
virtual bool is_empty() const = 0;
|
||||
bool is_nonempty() const { return !this->is_empty(); }
|
||||
/* true if source is currently empty (has 0 events to deliver) */
|
||||
virtual bool is_empty() const = 0;
|
||||
bool is_nonempty() const { return !this->is_empty(); }
|
||||
|
||||
/* true when source knows its next event
|
||||
* A source that isn't primed is also excluded from simulation
|
||||
* heap until it becomes primed.
|
||||
* This make feasible simulation sources that
|
||||
* depend on other simulation sources
|
||||
*/
|
||||
virtual bool is_primed() const { return !this->is_empty(); }
|
||||
virtual bool is_notprimed() const { return this->is_empty(); }
|
||||
/* true when source knows its next event
|
||||
* A source that isn't primed is also excluded from simulation
|
||||
* heap until it becomes primed.
|
||||
* This make feasible simulation sources that
|
||||
* depend on other simulation sources
|
||||
*/
|
||||
virtual bool is_primed() const { return !this->is_empty(); }
|
||||
virtual bool is_notprimed() const { return this->is_empty(); }
|
||||
|
||||
/* if true, this source has no events, and will never publish more events
|
||||
* - for sim, return true for a standalone source that has replayed all events
|
||||
* - for rt, set during orderly
|
||||
*/
|
||||
virtual bool is_exhausted() const = 0;
|
||||
/* if true, this source has no events, and will never publish more events
|
||||
* - for sim, return true for a standalone source that has replayed all events
|
||||
* - for rt, set during orderly
|
||||
*/
|
||||
virtual bool is_exhausted() const = 0;
|
||||
|
||||
/* if this is a simulation source and .is_exhausted is false:
|
||||
* returns next event time; more precisely, no events exist prior to
|
||||
* this time.
|
||||
*
|
||||
* if sim, and .is_primed = true,
|
||||
* returns timestamp of next event
|
||||
*/
|
||||
virtual utc_nanos sim_current_tm() const = 0;
|
||||
/* if this is a simulation source and .is_exhausted is false:
|
||||
* returns next event time; more precisely, no events exist prior to
|
||||
* this time.
|
||||
*
|
||||
* if sim, and .is_primed = true,
|
||||
* returns timestamp of next event
|
||||
*/
|
||||
virtual utc_nanos sim_current_tm() const = 0;
|
||||
|
||||
/* promise:
|
||||
* - .current_tm() > tm || .is_notprimed() || .is_exhausted() = true
|
||||
* - if replay_flag is true, then any events between previous .current_tm()
|
||||
* and new .current_tm() will have been published
|
||||
*
|
||||
* returns #of events delivered.
|
||||
* does not count events that were skipped, so always returns 0 if
|
||||
* replay_flag is false
|
||||
*/
|
||||
virtual std::uint64_t sim_advance_until(utc_nanos tm, bool replay_flag) = 0;
|
||||
/* promise:
|
||||
* - .current_tm() > tm || .is_notprimed() || .is_exhausted() = true
|
||||
* - if replay_flag is true, then any events between previous .current_tm()
|
||||
* and new .current_tm() will have been published
|
||||
*
|
||||
* returns #of events delivered.
|
||||
* does not count events that were skipped, so always returns 0 if
|
||||
* replay_flag is false
|
||||
*/
|
||||
virtual std::uint64_t sim_advance_until(utc_nanos tm, bool replay_flag) = 0;
|
||||
|
||||
/* informs source when it's added to a reactor
|
||||
/* informs source when it's added to a reactor
|
||||
|
||||
* (see Reactor.add_source())
|
||||
*/
|
||||
virtual void notify_reactor_add(Reactor * /*reactor*/) {}
|
||||
* (see Reactor.add_source())
|
||||
*/
|
||||
virtual void notify_reactor_add(Reactor * /*reactor*/) {}
|
||||
|
||||
/* informs source when it's removed from a reactor
|
||||
* (see Reactor.remove_source())
|
||||
*/
|
||||
virtual void notify_reactor_remove(Reactor * /*reactor*/) {}
|
||||
/* informs source when it's removed from a reactor
|
||||
* (see Reactor.remove_source())
|
||||
*/
|
||||
virtual void notify_reactor_remove(Reactor * /*reactor*/) {}
|
||||
|
||||
// ----- Inherited from AbstractSource -----
|
||||
// ----- Inherited from AbstractSource -----
|
||||
|
||||
/* deliver one event to attached sink
|
||||
* interpretation of 'one event' is source-specific;
|
||||
* could be a collapsed or batched event in practice.
|
||||
*
|
||||
* no-op if source is empty.
|
||||
*
|
||||
* if sim, promise:
|
||||
* - new .current_tm >= old .current_tm() || .is_notprimed() || .is_exhausted()
|
||||
*
|
||||
* returns #of events delivered. Must be 0 or 1 in this context
|
||||
*/
|
||||
virtual std::uint64_t deliver_one() override = 0;
|
||||
/* deliver one event to attached sink
|
||||
* interpretation of 'one event' is source-specific;
|
||||
* could be a collapsed or batched event in practice.
|
||||
*
|
||||
* no-op if source is empty.
|
||||
*
|
||||
* if sim, promise:
|
||||
* - new .current_tm >= old .current_tm() || .is_notprimed() || .is_exhausted()
|
||||
*
|
||||
* returns #of events delivered. Must be 0 or 1 in this context
|
||||
*/
|
||||
virtual std::uint64_t deliver_one() override = 0;
|
||||
|
||||
protected:
|
||||
/* default implementations for online sources */
|
||||
utc_nanos online_current_tm() const;
|
||||
uint64_t online_advance_until(utc_nanos tm, bool replay_flag);
|
||||
}; /*ReactorSource*/
|
||||
protected:
|
||||
/* default implementations for online sources */
|
||||
utc_nanos online_current_tm() const;
|
||||
uint64_t online_advance_until(utc_nanos tm, bool replay_flag);
|
||||
}; /*ReactorSource*/
|
||||
|
||||
using ReactorSourcePtr = ref::rp<ReactorSource>;
|
||||
} /*namespace reactor*/
|
||||
using ReactorSourcePtr = ref::rp<ReactorSource>;
|
||||
} /*namespace reactor*/
|
||||
} /*namespace xo*/
|
||||
|
||||
/* end ReactorSource.hpp */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue