OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | |
3 * | |
4 * Use of this source code is governed by a BSD-style license | |
5 * that can be found in the LICENSE file in the root of the source | |
6 * tree. An additional intellectual property rights grant can be found | |
7 * in the file PATENTS. All contributing project authors may | |
8 * be found in the AUTHORS file in the root of the source tree. | |
9 */ | |
10 | |
11 #ifndef WEBRTC_COMMON_AUDIO_SWAP_QUEUE_H_ | |
12 #define WEBRTC_COMMON_AUDIO_SWAP_QUEUE_H_ | |
13 | |
14 #include <algorithm> | |
15 #include <utility> | |
16 #include <vector> | |
17 | |
18 #include "webrtc/base/checks.h" | |
19 #include "webrtc/base/criticalsection.h" | |
20 | |
21 namespace webrtc { | |
22 | |
23 namespace internal { | |
24 | |
25 // This class is a one-way queue where data is written from one end and read | |
26 // from the other end. The queue can be applied to any swappable objects. | |
27 // The queue is safe to access the class concurrently from multiple threads. | |
28 // | |
29 // Conceptually, the queue maintains an ordered sequence and an unordered bunch | |
30 // of Ts. At all times, the number of Ts in the sequence and the bunch combined | |
31 // is N, a constant set in the constructor call. The following operations | |
32 // modify the sequence and the bunch: | |
33 // | |
34 // - The constructor populates the bunch with N Ts (either by | |
35 // default-constructing them or copy-constructing them from a supplied | |
36 // prototype T), and leaves the sequence empty. | |
37 // | |
38 // - Insert() steals the given T and puts it last in the sequence; it gives | |
39 // back an arbitrary T from the bunch. (Accomplished with a single swap, by | |
40 // reassigning the physical location of the removed bunch T to the | |
41 // sequence.) | |
42 // | |
43 // - Remove() steals the given T and puts it in the bunch; it gives back the | |
44 // first element in the sequence. (Accomplished with a single swap, by | |
45 // reassigning the physical location of the removed sequence T to the | |
46 // bunch.) | |
47 // | |
48 // - Clear() moves all Ts from the sequence into the bunch. (This is done | |
49 // without touching any Ts, by reassigning their physical locations.) | |
50 // | |
51 // The intended use is for one client (the producer) to fill a T with useful | |
52 // stuff, and use Insert() to swap it for a T that doesn't contain useful | |
53 // stuff; and for another client (the consumer) to use Remove() to swap a T | |
54 // that doesn't contain useful stuff for a T that does. The point of passing Ts | |
55 // that don't contain anything useful in the reverse direction is to avoid | |
56 // having to make heap allocations at the producer and releasing them at the | |
57 // consumer. | |
58 // | |
59 // Example of queue usage: | |
60 // SwapQueue<int> q(2)); // q contains [0 0]; | |
61 // int i = 1; | |
62 // q.Insert(&i); // q contains [1 0], i=0 | |
63 // i = 2; | |
64 // q.Insert(&i); // q contains [1 2], i=0 | |
65 // i = -3(; | |
66 // q.Remove(&i); // q contains [-3 2], i=1 | |
67 // i = 4; | |
68 // q.Insert(&i); // q contains [4 2], i=-3 | |
69 // i = -5; | |
70 // q.Remove(&i); // q contains [4 -5], i=2 | |
71 // i = -6; | |
72 // q.Remove(&i); // q contains [-6 -5], i=4 | |
73 // | |
74 // It should be noted that if you want the T returned from the bunch at the call | |
75 // to Insert to be of a certain characteristic (e.g., certain size), care must | |
76 // be taken that the queue is initialized with such elements, and that all Ts | |
77 // used as input to Remove also have that characteristic. In order to verify | |
78 // this invariance a callback function can be supplied that verifies this in | |
79 // debug mode (via RTC_DCHECK) for the queue elements. Examples of this can be | |
80 // found in the unit tests. | |
kwiberg-webrtc
2015/10/15 08:55:40
This text would fit better immediately preceding t
kwiberg-webrtc
2015/10/15 12:47:37
Also, Fredrik and I worked out an alternative text
peah-webrtc
2015/10/23 09:11:19
I like that :-) Will change!
| |
81 | |
82 // (Internal; please don't use outside this file.) | |
83 // Default item invariance verifier callback function. | |
84 template <typename T> | |
85 bool SwapQueueDefaultItemVerifier(const T&) { | |
86 return true; | |
87 } | |
88 | |
89 } // namespace internal | |
90 | |
91 // Queue template implementing a queue of elements of type T and with an | |
92 // optional invariance verifier callback function that verifies | |
the sun
2015/10/15 08:44:00
Didn't you just say the verifier function doesn't
peah-webrtc
2015/10/23 09:11:19
Good find! Will fix!
peah-webrtc
2015/10/23 09:11:19
Done.
| |
93 // that the queue elements are compliant to a certain requirement. | |
94 template <typename T, | |
95 bool (*ItemVerifier)(const T&) = | |
the sun
2015/10/15 08:44:01
I like ItemVerifier
kwiberg-webrtc
2015/10/15 08:55:40
+1
peah-webrtc
2015/10/23 09:11:19
Acknowledged.
peah-webrtc
2015/10/23 09:11:19
Acknowledged.
| |
96 internal::SwapQueueDefaultItemVerifier> | |
97 class SwapQueue { | |
98 public: | |
99 // Creates a queue of size size and fills it with the specified number of | |
100 // default constructed Ts. | |
101 explicit SwapQueue(size_t size) : queue_(size) { VerifyQueueContent(); } | |
102 | |
103 // Creates a queue of size size and fills it with copies of prototype. | |
104 SwapQueue(size_t size, const T& prototype) : queue_(size, prototype) { | |
105 VerifyQueueContent(); | |
106 } | |
107 | |
108 // Resets the queue to have zero content. | |
109 void Clear() { | |
110 rtc::CritScope cs(&crit_queue_); | |
111 next_write_index_ = 0; | |
112 next_read_index_ = 0; | |
113 num_elements_ = 0; | |
114 } | |
115 | |
116 // Inserts a T into the queue by swapping *input with an element already in | |
117 // the queue (an object from the unordered bunch). | |
118 // Returns true if the item was inserted or false if not (the queue was full). | |
119 // When specified, the T given in *input must pass the ItemVerifier() test. | |
120 // The contents of *input after the call are then also guaranteed to pass the | |
121 // ItemVerifier() test. | |
122 bool Insert(T* input) { | |
123 RTC_DCHECK(input); | |
124 RTC_DCHECK(ItemVerifier(*input)); | |
125 | |
126 rtc::CritScope cs(&crit_queue_); | |
127 | |
128 if (num_elements_ == queue_.size()) { | |
129 return false; | |
130 } | |
131 | |
132 using std::swap; | |
the sun
2015/10/19 10:36:12
Maybe a comment here why using std::swap is above
kwiberg-webrtc
2015/10/19 10:47:17
Hmm. Difficult to find a comment that's unobtrusiv
peah-webrtc
2015/10/23 09:11:19
I'd also prefer to keep it silent, since it is a s
| |
133 swap(*input, queue_[next_write_index_]); | |
134 | |
135 next_write_index_++; | |
136 if (next_write_index_ == queue_.size()) { | |
137 next_write_index_ = 0; | |
138 } | |
139 | |
140 num_elements_++; | |
141 return true; | |
142 } | |
143 | |
144 // Removes a T from the queue by swapping *output with an element in the | |
145 // queue. | |
146 // The T in *output before the call is swapped into the queue (into the | |
147 // unordered bunch in the queue). | |
148 // Returns true if an item could be removed or false if not (the queue was | |
149 // empty). When specified, The T given in *output must pass the ItemVerifier() | |
150 // test and the contents of *output after the call are then also guaranteed to | |
151 // pass the ItemVerifier() test. | |
152 bool Remove(T* output) { | |
153 RTC_DCHECK(output); | |
154 RTC_DCHECK(ItemVerifier(*output)); | |
155 | |
156 rtc::CritScope cs(&crit_queue_); | |
157 | |
158 if (num_elements_ == 0) { | |
159 return false; | |
160 } | |
161 | |
162 using std::swap; | |
163 swap(*output, queue_[next_read_index_]); | |
164 | |
165 next_read_index_++; | |
166 if (next_read_index_ == queue_.size()) { | |
167 next_read_index_ = 0; | |
168 } | |
169 | |
170 num_elements_--; | |
171 return true; | |
172 } | |
173 | |
174 private: | |
175 // Verify that the queue content complies with the ItemVerifier test. | |
176 void VerifyQueueContent() { | |
the sun
2015/10/15 08:44:00
For extra niceness, if we let this function return
kwiberg-webrtc
2015/10/15 08:55:40
Yes, good idea. And as an added bonus, the line nu
peah-webrtc
2015/10/23 09:11:19
Done.
peah-webrtc
2015/10/23 09:11:19
Awesome!
peah-webrtc
2015/10/23 09:11:19
Acknowledged.
| |
177 rtc::CritScope cs(&crit_queue_); | |
178 for (const auto& v : queue_) { | |
179 RTC_DCHECK(ItemVerifier(v)); | |
180 } | |
181 } | |
182 | |
183 // queue_.size() is constant. | |
184 std::vector<T> queue_ GUARDED_BY(crit_queue_); | |
185 | |
186 // (next_read_index_ + num_elements_) % queue_.size() = | |
187 // next_write_index_ | |
188 // 0 <= next_write_index_ <= queue.size() | |
189 size_t next_write_index_ GUARDED_BY(crit_queue_) = 0; | |
190 // 0 <= next_read_index_ <= queue.size() | |
191 size_t next_read_index_ GUARDED_BY(crit_queue_) = 0; | |
192 | |
193 // 0 <= num_elements_ <= queue.size() | |
194 size_t num_elements_ GUARDED_BY(crit_queue_) = 0; | |
195 | |
196 rtc::CriticalSection crit_queue_; | |
197 | |
198 RTC_DISALLOW_COPY_AND_ASSIGN(SwapQueue); | |
199 }; | |
200 | |
201 } // namespace webrtc | |
202 | |
203 #endif // WEBRTC_COMMON_AUDIO_SWAP_QUEUE_H_ | |
OLD | NEW |