diff --git a/Concurrency/AsyncTaskQueue.cpp b/Concurrency/AsyncTaskQueue.cpp index 4202cd275..571421d65 100644 --- a/Concurrency/AsyncTaskQueue.cpp +++ b/Concurrency/AsyncTaskQueue.cpp @@ -79,3 +79,20 @@ void AsyncTaskQueue::flush() { flush_condition->wait(lock); #endif } + +void DeferringAsyncTaskQueue::defer(std::function function) { + if(!deferred_tasks_) { + deferred_tasks_.reset(new std::list>); + } + deferred_tasks_->push_back(function); +} + +void DeferringAsyncTaskQueue::perform() { + std::shared_ptr>> deferred_tasks = deferred_tasks_; + deferred_tasks_.reset(); + enqueue([deferred_tasks] { + for(auto &function : *deferred_tasks) { + function(); + } + }); +} diff --git a/Concurrency/AsyncTaskQueue.hpp b/Concurrency/AsyncTaskQueue.hpp index e426453f7..be8517454 100644 --- a/Concurrency/AsyncTaskQueue.hpp +++ b/Concurrency/AsyncTaskQueue.hpp @@ -59,6 +59,37 @@ class AsyncTaskQueue { #endif }; +/*! + A deferring async task queue is one that accepts a list of functions to be performed but defers + any action until told to perform. It performs them by enquing a single asynchronous task that will + perform the deferred tasks in order. + + It therefore offers similar semantics to an asynchronous task queue, but allows for management of + synchronisation costs, since neither defer nor perform make any effort to be thread safe. +*/ +class DeferringAsyncTaskQueue: public AsyncTaskQueue { + public: + /*! + Adds a function to the deferral list. + + This is not thread safe; it should be serialised with other calls to itself and to perform. + */ + void defer(std::function function); + + /*! + Enqueues a function that will perform all currently deferred functions, in the + order that they were deferred. + + This is not thread safe; it should be serialised with other calls to itself and to defer. + */ + void perform(); + + private: + // TODO: this is a shared_ptr because of the issues capturing moveables in C++11; + // switch to a unique_ptr if/when adapting to C++14 + std::shared_ptr>> deferred_tasks_; +}; + } #endif /* Concurrency_hpp */