RavEngine
Loading...
Searching...
No Matches
lockless_task_queue.h
1/*
2Copyright 2018 Google Inc. All Rights Reserved.
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS-IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17#ifndef RESONANCE_AUDIO_UTILS_LOCKLESS_TASK_QUEUE_H_
18#define RESONANCE_AUDIO_UTILS_LOCKLESS_TASK_QUEUE_H_
19
20#include <atomic>
21#include <cstdint>
22#include <functional>
23#include <vector>
24
25namespace vraudio {
26
27// Lock-less task queue which is thread safe for concurrent task producers and
28// single task consumers.
30 public:
31 // Alias for the task closure type.
32 typedef std::function<void()> Task;
33
34 // Constructor. Preallocates nodes on the task queue list.
35 //
36 // @param max_tasks Maximum number of tasks on the task queue.
37 explicit LocklessTaskQueue(size_t max_tasks);
38
40
41 // Posts a new task to task queue.
42 //
43 // @param task Task to process.
44 void Post(Task&& task);
45
46 // Executes all tasks on the task queue.
47 void Execute();
48
49 // Removes all tasks on the task queue.
50 void Clear();
51
52 private:
53 // To prevent ABA problems during thread synchronization, the most significant
54 // 32 bits of this index type are reserved for a continuously increasing
55 // tag counter. This prevents cases where nodes on the head appears to be
56 // untouched during the preparation of a push operation but instead they have
57 // been popped and pushed back during a context switch.
58 typedef uint64_t TagAndIndex;
59
60 // Node to model a single-linked list.
61 struct Node {
62 Node() = default;
63
64 // Dummy copy constructor to enable vector::resize allocation.
65 Node(const Node& node) : next() {}
66
67 // User task.
68 LocklessTaskQueue::Task task;
69
70 // Index to next node.
71 std::atomic<TagAndIndex> next;
72 };
73
74 // Returned a TagAndIndex with increased tag.
75 TagAndIndex IncreaseTag(TagAndIndex tag_and_index);
76
77 // Extracts the index in the least significant 32 bits from a TagAndIndex.
78 TagAndIndex GetIndex(TagAndIndex tag_and_index);
79
80 // Extracts the flag in the most significant 32 bits from a TagAndIndex.
81 TagAndIndex GetFlag(TagAndIndex tag_and_index);
82
83 // Pushes a node to the front of a list.
84 //
85 // @param list_head Index to list head.
86 // @param node Index of node to be pushed to the front of the list.
87 void PushNodeToList(std::atomic<TagAndIndex>* list_head, TagAndIndex node);
88
89 // Pops a node from the front of a list.
90 //
91 // @param list_head Index to list head.
92 // @return Index of front node, kInvalidIndex if list is empty.
93 TagAndIndex PopNodeFromList(std::atomic<TagAndIndex>* list_head);
94
95 // Iterates over list and moves all tasks to |temp_tasks_| to be executed in
96 // FIFO order. All processed nodes are pushed back to the free list.
97 //
98 // @param list_head Index of head node of list to be processed.
99 // @param execute If true, tasks on task list are executed.
100 void ProcessTaskList(TagAndIndex list_head, bool execute);
101
102 // Initializes task queue structures and preallocates task queue nodes.
103 //
104 // @param num_nodes Number of nodes to be initialized on free list.
105 void Init(size_t num_nodes);
106
107 // Index to head node of free list.
108 std::atomic<TagAndIndex> free_list_head_idx_;
109
110 // Index to head node of task list.
111 std::atomic<TagAndIndex> task_list_head_idx_;
112
113 // Holds preallocated nodes.
114 std::vector<Node> nodes_;
115
116 // Temporary vector to hold |Task|s in order to execute them in reverse order
117 // (FIFO, instead of LIFO).
118 std::vector<Task> temp_tasks_;
119};
120
121} // namespace vraudio
122
123#endif // RESONANCE_AUDIO_UTILS_LOCKLESS_TASK_QUEUE_H_
Definition lockless_task_queue.h:29