For timeouts in event reactors and proactors I use a priority queue that also allows O(log(n)) random access removes of events (when the event is signalled/completes rather than a timeout occurring). I store std::pair<std::steady_clock::time_point, Timed *>
where Timed
is a class that adds has an index (pointing into the queue) to allow efficient removal when calling TimedQ::Remove(Timed *p)
. When I want to have an event type associated with a timeout, I derive from Timed
. The queue's Top()
and Pop()
return a pair.
I used to have a a bunch of code using the queue such as
std::tie(timePt0, eventPtr0) = timeoutQ.Pop();
std::tie(timePt1, eventPtr1) = std::move(hold);
which worked fine before I started using a base class Timed *
in the queue instead of specific event type (i.e. Timed
was originally a templated type instead), as I eventually needed to support multiple different event types that can be associated with the timeouts. However, with eventPtr*
being a derived type (that I can static_cast
to from a Timed *
returned by the queue), code like the above no longer works.
I'm wondering what's the best way to do this. Right now, it's ended up very verbose, and I'm concerned about efficiencies like temporaries being created as well:
auto v(timeoutQ.Pop());
timePt0 = v.first;
eventPtr0 = static_cast<TimedEvent *>(v.second);
std::tie(timePt1, eventPtr1) = std::move(std::make_pair(hold.first, static_cast<TimedEvent *>(hold.second)); // I didn't literally do it like this, but I'm just trying to illustrate my struggle
The only other idea I had was to template the functions that return a pair by the derived event class, but this seems poor from a code size perspective, as multiple instances of those functions will be created even though the machine code should be identical since in all cases it's a pointer that's stored.
Aucun commentaire:
Enregistrer un commentaire