Ewout van Bekkum | 04f1292 | 2021-08-05 19:34:52 -0700 | [diff] [blame] | 1 | .. _module-pw_work_queue: |
| 2 | |
| 3 | ============= |
| 4 | pw_work_queue |
| 5 | ============= |
| 6 | The ``pw_work_queue`` module contains utilities for deferring work to be |
| 7 | executed by another thread. |
| 8 | |
| 9 | .. Warning:: |
| 10 | This module is still under construction, the API is not yet stable. |
| 11 | |
| 12 | --------- |
| 13 | WorkQueue |
| 14 | --------- |
| 15 | The ``pw::work_queue::WorkQueue`` class enables threads and interrupts to |
| 16 | enqueue work as a ``pw::work_queue::WorkItem`` for execution by the work queue. |
| 17 | |
| 18 | The entire API is thread and interrupt safe. |
| 19 | |
| 20 | Queue Sizing |
| 21 | ============ |
| 22 | The number of outstanding work requests is limited based on the |
| 23 | ``pw::work_queue::WorkQueue``'s internal queue size. This must be set |
| 24 | appropriately for the application by the user. |
| 25 | |
| 26 | The queue size is set trough either through the size of the ``queue_storage`` |
| 27 | buffer passed into the constructor or by using the templated |
| 28 | ``pw::work_queue::WorkQueueWithBuffer`` helper. |
| 29 | |
| 30 | .. Note:: While the queue is full, the queue will not accept further work. |
| 31 | |
| 32 | Cooperative Thread Cancellation |
| 33 | =============================== |
| 34 | The class is a ``pw::thread::ThreadCore``, meaning it should be executed as a |
| 35 | single thread. In order to facilitate clean shutdown, it provides a |
| 36 | ``RequestStop()`` API for cooperative cancellation which should be invoked |
| 37 | before joining the thread. |
| 38 | |
| 39 | .. Note:: Once stop has been requested the queue will no longer accept further |
| 40 | work. |
| 41 | |
| 42 | C++ |
| 43 | === |
| 44 | .. cpp:class:: pw::work_queue::WorkQueue |
| 45 | |
| 46 | .. cpp:function:: Status PushWork(WorkItem work_item) |
| 47 | |
| 48 | Enqueues a work_item for execution by the work queue thread. |
| 49 | |
| 50 | Returns: |
| 51 | |
| 52 | * **Ok** - Success, entry was enqueued for execution. |
| 53 | * **FailedPrecondition** - the work queue is shutting down, entries are no |
| 54 | longer permitted. |
| 55 | * **ResourceExhausted** - internal work queue is full, entry was not |
| 56 | enqueued. |
| 57 | |
| 58 | .. cpp:function:: void CheckPushWork(WorkItem work_item) |
| 59 | |
| 60 | Queue work for execution. Crash if the work cannot be queued due to a |
| 61 | full queue or a stopped worker thread. |
| 62 | |
| 63 | This call is recommended where possible since it saves error handling code |
| 64 | at the callsite; and in many practical cases, it is a bug if the work |
| 65 | queue is full (and so a crash is useful to detect the problem). |
| 66 | |
| 67 | **Precondition:** The queue must not overflow, i.e. be full. |
| 68 | |
| 69 | **Precondition:** The queue must not have been requested to stop, i.e. it |
| 70 | must not be in the process of shutting down. |
| 71 | |
| 72 | .. cpp:function:: void RequestStop() |
| 73 | |
| 74 | Locks the queue to prevent further work enqueing, finishes outstanding |
| 75 | work, then shuts down the worker thread. |
| 76 | |
| 77 | The WorkQueue cannot be resumed after stopping as the ThreadCore thread |
| 78 | returns and may be joined. It must be reconstructed for re-use after |
| 79 | the thread has been joined. |
| 80 | |
| 81 | Example |
| 82 | ------- |
| 83 | |
| 84 | .. code-block:: cpp |
| 85 | |
| 86 | #include "pw_thread/detached_thread.h" |
| 87 | #include "pw_work_queue/work_queue.h" |
| 88 | |
| 89 | pw::work_queue::WorkQueueWithBuffer<10> work_queue; |
| 90 | |
| 91 | pw::thread::Options& WorkQueueThreadOptions(); |
| 92 | void SomeLongRunningProcessing(); |
| 93 | |
| 94 | void SomeInterruptHandler() { |
| 95 | // Instead of executing the long running processing task in the interrupt, |
| 96 | // the work_queue executes it on the interrupt's behalf. |
| 97 | work_queue.CheckPushWork(SomeLongRunningProcessing); |
| 98 | } |
| 99 | |
| 100 | int main() { |
| 101 | // Start up the work_queue as a detached thread which runs forever. |
| 102 | pw::thread::DetachedThread(WorkQueueThreadOptions(), work_queue); |
| 103 | } |
| 104 | |