. Clients have
+ const access to that graph to perform additional operations not
+ directly provided by BasicNetwork.
Peer Requirements:
@@ -91,198 +77,40 @@ namespace csf {
u < v bool LessThanComparable
std::hash class std::hash is defined for P
! u bool true if u is not-a-peer
+
*/
template
class BasicNetwork
{
-public:
using peer_type = Peer;
- using clock_type = beast::manual_clock;
+ using clock_type = Scheduler::clock_type;
using duration = typename clock_type::duration;
using time_point = typename clock_type::time_point;
-private:
- struct by_to_tag
- {
- };
- struct by_from_tag
- {
- };
- struct by_when_tag
- {
- };
-
- using by_to_hook = boost::intrusive::list_base_hook<
- boost::intrusive::link_mode,
- boost::intrusive::tag>;
-
- using by_from_hook = boost::intrusive::list_base_hook<
- boost::intrusive::link_mode,
- boost::intrusive::tag>;
-
- using by_when_hook = boost::intrusive::set_base_hook<
- boost::intrusive::link_mode>;
-
- struct msg : by_to_hook, by_from_hook, by_when_hook
- {
- Peer to;
- Peer from;
- time_point when;
-
- msg(msg const&) = delete;
- msg&
- operator=(msg const&) = delete;
- virtual ~msg() = default;
- virtual void
- operator()() const = 0;
-
- msg(Peer const& from_, Peer const& to_, time_point when_)
- : to(to_), from(from_), when(when_)
- {
- }
-
- bool
- operator<(msg const& other) const
- {
- return when < other.when;
- }
- };
-
- template
- class msg_impl : public msg
- {
- private:
- Handler const h_;
-
- public:
- msg_impl(msg_impl const&) = delete;
- msg_impl&
- operator=(msg_impl const&) = delete;
-
- msg_impl(
- Peer const& from_,
- Peer const& to_,
- time_point when_,
- Handler&& h)
- : msg(from_, to_, when_), h_(std::move(h))
- {
- }
-
- msg_impl(
- Peer const& from_,
- Peer const& to_,
- time_point when_,
- Handler const& h)
- : msg(from_, to_, when_), h_(h)
- {
- }
-
- void
- operator()() const override
- {
- h_();
- }
- };
-
- class queue_type
- {
- private:
- using by_to_list = typename boost::intrusive::make_list<
- msg,
- boost::intrusive::base_hook,
- boost::intrusive::constant_time_size>::type;
-
- using by_from_list = typename boost::intrusive::make_list<
- msg,
- boost::intrusive::base_hook,
- boost::intrusive::constant_time_size>::type;
-
- using by_when_set = typename boost::intrusive::make_multiset<
- msg,
- boost::intrusive::constant_time_size>::type;
-
- qalloc alloc_;
- by_when_set by_when_;
- std::unordered_map by_to_;
- std::unordered_map by_from_;
-
- public:
- using iterator = typename by_when_set::iterator;
-
- queue_type(queue_type const&) = delete;
- queue_type&
- operator=(queue_type const&) = delete;
-
- explicit queue_type(qalloc const& alloc);
-
- ~queue_type();
-
- bool
- empty() const;
-
- iterator
- begin();
-
- iterator
- end();
-
- template
- typename by_when_set::iterator
- emplace(Peer const& from, Peer const& to, time_point when, Handler&& h);
-
- void
- erase(iterator iter);
-
- void
- remove(Peer const& from, Peer const& to);
- };
-
struct link_type
{
- bool inbound;
- duration delay;
-
- link_type(bool inbound_, duration delay_)
- : inbound(inbound_), delay(delay_)
+ bool inbound = false;
+ duration delay{};
+ time_point established{};
+ link_type() = default;
+ link_type(bool inbound_, duration delay_, time_point established_)
+ : inbound(inbound_), delay(delay_), established(established_)
{
}
};
- using links_type = boost::container::flat_map;
-
- class link_transform;
-
- qalloc alloc_;
- queue_type queue_;
- // VFALCO This is an ugly wart, aged containers
- // want a non-const reference to a clock.
- clock_type mutable clock_;
- std::unordered_map links_;
+ Scheduler& scheduler;
+ Digraph links_;
public:
BasicNetwork(BasicNetwork const&) = delete;
BasicNetwork&
operator=(BasicNetwork const&) = delete;
- BasicNetwork();
-
- /** Return the allocator. */
- qalloc const&
- alloc() const;
-
- /** Return the clock. */
- clock_type&
- clock() const;
-
- /** Return the current network time.
-
- @note The epoch is unspecified
- */
- time_point
- now() const;
+ BasicNetwork(Scheduler& s);
/** Connect two peers.
@@ -327,13 +155,6 @@ class BasicNetwork
bool
disconnect(Peer const& peer1, Peer const& peer2);
- /** Return the range of active links.
-
- @return A random access range.
- */
- boost::transformed_range
- links(Peer const& from);
-
/** Send a message to a peer.
Preconditions:
@@ -356,335 +177,33 @@ class BasicNetwork
void
send(Peer const& from, Peer const& to, Function&& f);
- // Used to cancel timers
- struct cancel_token;
-
- /** Deliver a timer notification.
-
- Effects:
-
- When the network time is reached,
- the function will be called with
- no arguments.
- */
- template
- cancel_token
- timer(time_point const& when, Function&& f);
-
- /** Deliver a timer notification.
-
- Effects:
-
- When the specified time has elapsed,
- the function will be called with
- no arguments.
- */
- template
- cancel_token
- timer(duration const& delay, Function&& f);
-
- /** Cancel a timer.
-
- Preconditions:
-
- `token` was the return value of a call
- timer() which has not yet been invoked.
- */
- void
- cancel(cancel_token const& token);
-
- /** Perform breadth-first search.
-
- Function will be called with this signature:
-
- void(std::size_t, Peer&);
-
- The second argument is the distance of the
- peer from the start peer, in hops.
- */
- template
- void
- bfs(Peer const& start, Function&& f);
-
- /** Run the network for up to one message.
-
- Effects:
-
- The clock is advanced to the time
- of the last delivered message.
-
- @return `true` if a message was processed.
- */
- bool
- step_one();
-
- /** Run the network until no messages remain.
-
- Effects:
-
- The clock is advanced to the time
- of the last delivered message.
-
- @return `true` if any message was processed.
- */
- bool
- step();
-
- /** Run the network while a condition is true.
-
- Function takes no arguments and will be called
- repeatedly after each message is processed to
- decide whether to continue.
-
- Effects:
-
- The clock is advanced to the time
- of the last delivered message.
- @return `true` if any message was processed.
- */
- template
- bool
- step_while(Function&& func);
-
- /** Run the network until the specified time.
-
- Effects:
-
- The clock is advanced to the
- specified time.
-
- @return `true` if any messages remain.
- */
- bool
- step_until(time_point const& until);
-
- /** Run the network until time has elapsed.
-
- Effects:
-
- The clock is advanced by the
- specified duration.
+ /** Return the range of active links.
- @return `true` if any messages remain.
+ @return A random access range over Digraph::Edge instances
*/
- template
- bool
- step_for(std::chrono::duration const& amount);
-};
-
-//------------------------------------------------------------------------------
-
-template
-BasicNetwork::queue_type::queue_type(qalloc const& alloc)
- : alloc_(alloc)
-{
-}
-
-template
-BasicNetwork::queue_type::~queue_type()
-{
- for (auto iter = by_when_.begin(); iter != by_when_.end();)
+ auto
+ links(Peer const& from)
{
- auto m = &*iter;
- ++iter;
- m->~msg();
- alloc_.dealloc(m, 1);
+ return links_.outEdges(from);
}
-}
-template
-inline bool
-BasicNetwork::queue_type::empty() const
-{
- return by_when_.empty();
-}
-
-template
-inline auto
-BasicNetwork::queue_type::begin() -> iterator
-{
- return by_when_.begin();
-}
-
-template