Skip to content

Using the Forque

kataklinger edited this page Nov 24, 2020 · 3 revisions

Forque is implemented by frq::forque class template which is parameterized by type of the items stored in the queue, type of tags used for scheduling, desired runque type and allocator.

template<typename Ty,
         runlike Runque,
         taglike Tag,
         typename Alloc = std::allocator<Ty>>
class forque;

Runque and Tag template parameters are constrained by runlike and taglike concepts.

frq::forque has rather simple interface that allows user to:

  1. reserve place in queue for already produced item with specific tag:
template<taglike Tag>
task<> reserve(Tag const& tag, value_type const& value); // (a)

template<taglike Tag>
task<> reserve(Tag const& tag, value_type&& value); // (b)
  1. reserve place in queue for an item with specific tag that will be produced later:
template<taglike Tag>
task<reservation_type> reserve(Tag const& tag); // (c)
  1. get access to next ready item in runqueue:
task<retainment_type> get() noexcept;
  1. stop acceptance of new reservations and processing of existing items
task<> interrupt() noexcept;

Producing Items

If item’s value is already known, it can be marked with desired tag and be placed in forque using reserve overloads (a) or (b). Item will be put in ready queue whenever its dependencies are processed. On the other hand if item’s value is not yet known, but the place has to be reserved to keep desired order of processing when it comes to item’s dependencies, overload (c) can be used. It returns object of reservation<T> type which represents this reservation. Calling release() on this type will set desired value and it will allow item to be put in ready queue. If release() is not called, all dependent items will be stuck in forque and they will not be scheduled for processing.

Consuming Items

get()will return only when there are available items in runqueue, or if the processing is interrupted by throwing interrupted exception. Item is not considered consumed after calling get(). Instead instance of retainment<T> type is returned. Calling value() will yield item’s value and finalize() will mark item as consumed and forque can proceed with processing dependent items. finalize() will not be called automatically by the destructor of retainment<T>, so it’s user’s responsibility to invoke it even in case of exception. If finalize() is not invoked, all dependent items will be stuck in forqueu and will never be scheduled for processing.

Stopping the Item Processing

Invoking interrupt() will immediately awake any consumers waiting for items and throw interrupted exception within their context. Any subsequent call to reserve() or get() will also result in interrupted exception.

Clone this wiki locally