// // AsyncTaskQueue.hpp // Clock Signal // // Created by Thomas Harte on 07/10/2016. // Copyright 2016 Thomas Harte. All rights reserved. // #ifndef AsyncTaskQueue_hpp #define AsyncTaskQueue_hpp #include #include #include #include #include #include #include #if defined(__APPLE__) && !defined(IGNORE_APPLE) #include #define USE_GCD #endif namespace Concurrency { using TaskList = std::vector>; /*! An async task queue allows a caller to enqueue void(void) functions. Those functions are guaranteed to be performed serially and asynchronously from the caller. A caller may also request to flush, causing it to block until all previously-enqueued functions are complete. */ class AsyncTaskQueue { public: AsyncTaskQueue(); virtual ~AsyncTaskQueue(); /*! Adds @c function to the queue. @discussion Functions will be performed serially and asynchronously. This method is safe to call from multiple threads. @parameter function The function to enqueue. */ void enqueue(std::function function); /*! Blocks the caller until all previously-enqueud functions have completed. */ void flush(); private: #ifdef USE_GCD dispatch_queue_t serial_dispatch_queue_; #else std::atomic_bool should_destruct_; std::condition_variable processing_condition_; std::mutex queue_mutex_; std::list> pending_tasks_; std::thread thread_; #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: ~DeferringAsyncTaskQueue(); /*! 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(); /*! Blocks the caller until all previously-enqueud functions have completed. */ void flush(); private: std::unique_ptr deferred_tasks_; }; } #endif /* Concurrency_hpp */