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. | |
the sun
2015/10/26 15:16:20
objects -> type
peah-webrtc
2015/10/26 22:27:02
Please see below.
| |
27 // The queue is safe to access the class concurrently from multiple threads. | |
the sun
2015/10/26 15:16:20
Remove "the class"
peah-webrtc
2015/10/26 22:27:02
Please see below.
| |
28 // | |
29 // Conceptually, the queue maintains an ordered sequence and an unordered bunch | |
the sun
2015/10/26 15:16:21
Where's the shorter description that me and Karl s
peah-webrtc
2015/10/26 22:27:02
That is a very good question. Seems like something
| |
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. | |
81 | |
82 // (Internal; please don't use outside this file.) | |
83 // Default item invariance verifier callback function. | |
84 template <typename T> | |
85 bool SwapQueueItemVerifierFunction(const T&) { | |
86 return true; | |
87 } | |
88 | |
89 } // namespace internal | |
90 | |
91 // Functor to use when supplying a verifier function for the queue item | |
92 // verifcation. | |
93 template <typename T, | |
94 bool (*QueueItemVerifierFunction)(const T&) = | |
95 internal::SwapQueueItemVerifierFunction> | |
96 class SwapQueueItemVerifier { | |
97 public: | |
98 bool operator()(const T& t) const { return QueueItemVerifierFunction(t); } | |
99 }; | |
100 | |
101 // Queue template implementing a queue of elements of type T and with an | |
the sun
2015/10/26 15:16:21
Too verbose.
"Queue on type T."
peah-webrtc
2015/10/26 22:27:02
Done.
| |
102 // optional invariance verifier callback functor that verifies | |
103 // that the queue elements are compliant to a certain requirement. | |
104 template <typename T, typename QueueItemVerifier = SwapQueueItemVerifier<T> > | |
the sun
2015/10/26 15:16:21
QueueItemVerifier shouldn't be needed as a templat
peah-webrtc
2015/10/26 22:27:02
How do you mean? I still need to have the type of
the sun
2015/10/27 13:51:33
You're right. The template argument is needed.
peah-webrtc
2015/10/29 06:15:14
Acknowledged.
| |
105 class SwapQueue { | |
106 public: | |
107 // Creates a queue of size size and fills it with the specified number of | |
108 // default constructed Ts. | |
109 explicit SwapQueue(size_t size) : queue_(size) { | |
110 RTC_DCHECK(VerifyQueueContent()); | |
111 } | |
112 | |
113 // Creates a queue of size size and fills it with the specified number of | |
114 // default constructed Ts and accepts a functor to use for initializing the | |
115 // item verification functor. | |
116 explicit SwapQueue(size_t size, const QueueItemVerifier& queue_item_verifier) | |
the sun
2015/10/26 15:16:20
remove "explicit"
peah-webrtc
2015/10/26 22:27:02
Done.
| |
117 : queue_(size), queue_item_verifier_(queue_item_verifier) { | |
118 RTC_DCHECK(VerifyQueueContent()); | |
119 } | |
120 | |
121 // Creates a queue of size size and fills it with copies of prototype. | |
122 SwapQueue(size_t size, const T& prototype) : queue_(size, prototype) { | |
123 RTC_DCHECK(VerifyQueueContent()); | |
124 } | |
125 | |
126 // Creates a queue of size size and fills it with copies of prototype and | |
127 // accepts a functor to use for initializing the item verification functor. | |
128 SwapQueue(size_t size, | |
129 QueueItemVerifier const& queue_item_verifier, | |
130 const T& prototype) | |
131 : queue_(size, prototype), queue_item_verifier_(queue_item_verifier) { | |
132 RTC_DCHECK(VerifyQueueContent()); | |
133 } | |
134 | |
135 // Resets the queue to have zero content. | |
136 void Clear() { | |
137 rtc::CritScope cs(&crit_queue_); | |
138 next_write_index_ = 0; | |
139 next_read_index_ = 0; | |
140 num_elements_ = 0; | |
141 } | |
142 | |
143 // Inserts a T into the queue by swapping *input with an element already in | |
144 // the queue (an object from the unordered bunch). | |
145 // Returns true if the item was inserted or false if not (the queue was full). | |
146 // When specified, the T given in *input must pass the ItemVerifier() test. | |
147 // The contents of *input after the call are then also guaranteed to pass the | |
148 // ItemVerifier() test. | |
149 bool Insert(T* input) { | |
150 RTC_DCHECK(input); | |
151 RTC_DCHECK(queue_item_verifier_(*input)); | |
152 | |
153 rtc::CritScope cs(&crit_queue_); | |
154 | |
155 if (num_elements_ == queue_.size()) { | |
156 return false; | |
157 } | |
158 | |
159 using std::swap; | |
160 swap(*input, queue_[next_write_index_]); | |
161 | |
162 next_write_index_++; | |
163 if (next_write_index_ == queue_.size()) { | |
164 next_write_index_ = 0; | |
165 } | |
166 | |
167 num_elements_++; | |
168 return true; | |
169 } | |
170 | |
171 // Removes a T from the queue by swapping *output with an element in the | |
172 // queue. | |
173 // The T in *output before the call is swapped into the queue (into the | |
174 // unordered bunch in the queue). | |
175 // Returns true if an item could be removed or false if not (the queue was | |
176 // empty). When specified, The T given in *output must pass the ItemVerifier() | |
177 // test and the contents of *output after the call are then also guaranteed to | |
178 // pass the ItemVerifier() test. | |
179 bool Remove(T* output) { | |
180 RTC_DCHECK(output); | |
181 RTC_DCHECK(queue_item_verifier_(*output)); | |
182 | |
183 rtc::CritScope cs(&crit_queue_); | |
184 | |
185 if (num_elements_ == 0) { | |
186 return false; | |
187 } | |
188 | |
189 using std::swap; | |
190 swap(*output, queue_[next_read_index_]); | |
191 | |
192 next_read_index_++; | |
193 if (next_read_index_ == queue_.size()) { | |
194 next_read_index_ = 0; | |
195 } | |
196 | |
197 num_elements_--; | |
198 return true; | |
199 } | |
200 | |
201 private: | |
202 // Verify that the queue content complies with the ItemVerifier test. | |
203 bool VerifyQueueContent() { | |
204 rtc::CritScope cs(&crit_queue_); | |
205 for (const auto& v : queue_) { | |
206 RTC_DCHECK(queue_item_verifier_(v)); | |
207 } | |
208 | |
the sun
2015/10/26 15:16:20
remove blank
peah-webrtc
2015/10/26 22:27:02
Done.
| |
209 return true; | |
210 } | |
211 | |
212 // queue_.size() is constant. | |
213 std::vector<T> queue_ GUARDED_BY(crit_queue_); | |
214 | |
215 QueueItemVerifier queue_item_verifier_; | |
216 | |
217 // (next_read_index_ + num_elements_) % queue_.size() = | |
218 // next_write_index_ | |
219 // 0 <= next_write_index_ <= queue.size() | |
the sun
2015/10/26 15:16:21
next_write_index_ < queue.size()
peah-webrtc
2015/10/26 22:27:02
Done.
| |
220 size_t next_write_index_ GUARDED_BY(crit_queue_) = 0; | |
221 // 0 <= next_read_index_ <= queue.size() | |
the sun
2015/10/26 15:16:21
next_read_index_ < queue.size()
peah-webrtc
2015/10/26 22:27:02
Done.
| |
222 size_t next_read_index_ GUARDED_BY(crit_queue_) = 0; | |
223 | |
224 // 0 <= num_elements_ <= queue.size() | |
225 size_t num_elements_ GUARDED_BY(crit_queue_) = 0; | |
226 | |
227 rtc::CriticalSection crit_queue_; | |
the sun
2015/10/26 15:16:21
nit: I would have used the order:
queue_item_veri
peah-webrtc
2015/10/26 22:27:02
Makes sense! Will change to that.
peah-webrtc
2015/10/26 22:27:02
Done.
| |
228 | |
229 RTC_DISALLOW_COPY_AND_ASSIGN(SwapQueue); | |
230 }; | |
231 | |
232 } // namespace webrtc | |
233 | |
234 #endif // WEBRTC_COMMON_AUDIO_SWAP_QUEUE_H_ | |
OLD | NEW |