/src/mozilla-central/dom/media/doctor/gtest/TestMultiWriterQueue.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this file, |
5 | | * You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "MultiWriterQueue.h" |
8 | | |
9 | | #include "DDTimeStamp.h" |
10 | | #include "mozilla/Assertions.h" |
11 | | #include "nsDeque.h" |
12 | | #include "nsThreadUtils.h" |
13 | | |
14 | | #include <gtest/gtest.h> |
15 | | |
16 | | using mozilla::MultiWriterQueue; |
17 | | using mozilla::MultiWriterQueueDefaultBufferSize; |
18 | | using mozilla::MultiWriterQueueReaderLocking_Mutex; |
19 | | using mozilla::MultiWriterQueueReaderLocking_None; |
20 | | |
21 | | template<size_t BufferSize> |
22 | | static void |
23 | | TestMultiWriterQueueST(const int loops) |
24 | 0 | { |
25 | 0 | using Q = MultiWriterQueue<int, BufferSize>; |
26 | 0 | Q q; |
27 | 0 |
|
28 | 0 | int pushes = 0; |
29 | 0 | // Go through 2 cycles of pushes&pops, to exercize reusable buffers. |
30 | 0 | for (int max = loops; max <= loops * 2; max *= 2) { |
31 | 0 | // Push all numbers. |
32 | 0 | for (int i = 1; i <= max; ++i) { |
33 | 0 | bool newBuffer = q.Push(i); |
34 | 0 | // A new buffer should be added at the last push of each buffer. |
35 | 0 | EXPECT_EQ(++pushes % BufferSize == 0, newBuffer); |
36 | 0 | } |
37 | 0 |
|
38 | 0 | // Pop numbers, should be FIFO. |
39 | 0 | int x = 0; |
40 | 0 | q.PopAll([&](int& i) { EXPECT_EQ(++x, i); }); Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<1ul>(int)::{lambda(int&)#1}::operator()(int&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<2ul>(int)::{lambda(int&)#1}::operator()(int&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<4ul>(int)::{lambda(int&)#1}::operator()(int&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<10ul>(int)::{lambda(int&)#1}::operator()(int&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<8192ul>(int)::{lambda(int&)#1}::operator()(int&) const |
41 | 0 |
|
42 | 0 | // We should have got all numbers. |
43 | 0 | EXPECT_EQ(max, x); |
44 | 0 |
|
45 | 0 | // Nothing left. |
46 | 0 | q.PopAll([&](int&) { EXPECT_TRUE(false); }); Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<1ul>(int)::{lambda(int&)#2}::operator()(int&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<2ul>(int)::{lambda(int&)#2}::operator()(int&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<4ul>(int)::{lambda(int&)#2}::operator()(int&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<10ul>(int)::{lambda(int&)#2}::operator()(int&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<8192ul>(int)::{lambda(int&)#2}::operator()(int&) const |
47 | 0 | } |
48 | 0 | } Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<1ul>(int) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<2ul>(int) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<4ul>(int) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<10ul>(int) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueST<8192ul>(int) |
49 | | |
50 | | TEST(MultiWriterQueue, SingleThreaded) |
51 | 0 | { |
52 | 0 | TestMultiWriterQueueST<1>(10); |
53 | 0 | TestMultiWriterQueueST<2>(10); |
54 | 0 | TestMultiWriterQueueST<4>(10); |
55 | 0 |
|
56 | 0 | TestMultiWriterQueueST<10>(9); |
57 | 0 | TestMultiWriterQueueST<10>(10); |
58 | 0 | TestMultiWriterQueueST<10>(11); |
59 | 0 | TestMultiWriterQueueST<10>(19); |
60 | 0 | TestMultiWriterQueueST<10>(20); |
61 | 0 | TestMultiWriterQueueST<10>(21); |
62 | 0 | TestMultiWriterQueueST<10>(999); |
63 | 0 | TestMultiWriterQueueST<10>(1000); |
64 | 0 | TestMultiWriterQueueST<10>(1001); |
65 | 0 |
|
66 | 0 | TestMultiWriterQueueST<8192>(8192 * 4 + 1); |
67 | 0 | } |
68 | | |
69 | | template<typename Q> |
70 | | static void |
71 | | TestMultiWriterQueueMT(int aWriterThreads, |
72 | | int aReaderThreads, |
73 | | int aTotalLoops, |
74 | | const char* aPrintPrefix) |
75 | 0 | { |
76 | 0 | Q q; |
77 | 0 |
|
78 | 0 | const int threads = aWriterThreads + aReaderThreads; |
79 | 0 | const int loops = aTotalLoops / aWriterThreads; |
80 | 0 |
|
81 | 0 | nsIThread** array = new nsIThread*[threads]; |
82 | 0 |
|
83 | 0 | mozilla::Atomic<int> pushThreadsCompleted{ 0 }; |
84 | 0 | int pops = 0; |
85 | 0 |
|
86 | 0 | nsCOMPtr<nsIRunnable> popper = NS_NewRunnableFunction("MWQPopper", [&]() { |
87 | 0 | // int popsBefore = pops; |
88 | 0 | // int allocsBefore = q.AllocatedBuffersStats().mCount; |
89 | 0 | q.PopAll([&pops](const int& i) { ++pops; }); Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}::operator()(int const) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}::operator()(int const) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}::operator()(int const) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}::operator()(int const) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}::operator()(int const) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}::operator()(int const) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}::operator()(int const) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}::operator()(int const) const |
90 | 0 | // if (pops != popsBefore || |
91 | 0 | // q.AllocatedBuffersStats().mCount != allocsBefore) { |
92 | 0 | // printf("%s threads=1+%d loops/thread=%d pops=%d " |
93 | 0 | // "buffers: live=%d (w %d) reusable=%d (w %d) " |
94 | 0 | // "alloc=%d (w %d)\n", |
95 | 0 | // aPrintPrefix, |
96 | 0 | // aWriterThreads, |
97 | 0 | // loops, |
98 | 0 | // pops, |
99 | 0 | // q.LiveBuffersStats().mCount, |
100 | 0 | // q.LiveBuffersStats().mWatermark, |
101 | 0 | // q.ReusableBuffersStats().mCount, |
102 | 0 | // q.ReusableBuffersStats().mWatermark, |
103 | 0 | // q.AllocatedBuffersStats().mCount, |
104 | 0 | // q.AllocatedBuffersStats().mWatermark); |
105 | 0 | // } |
106 | 0 | }); Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*)::{lambda()#1}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*)::{lambda()#1}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*)::{lambda()#1}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*)::{lambda()#1}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda()#1}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda()#1}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda()#1}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda()#1}::operator()() const |
107 | 0 | // Cycle through reader threads. |
108 | 0 | mozilla::Atomic<size_t> readerThread{ 0 }; |
109 | 0 |
|
110 | 0 | double start = mozilla::ToSeconds(mozilla::DDNow()); |
111 | 0 |
|
112 | 0 | for (int k = 0; k < threads; k++) { |
113 | 0 | // First `aReaderThreads` threads to pop, all others to push. |
114 | 0 | if (k < aReaderThreads) { |
115 | 0 | nsCOMPtr<nsIThread> t; |
116 | 0 | nsresult rv = NS_NewNamedThread("MWQThread", getter_AddRefs(t)); |
117 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
118 | 0 | NS_ADDREF(array[k] = t); |
119 | 0 | } else { |
120 | 0 | nsCOMPtr<nsIThread> t; |
121 | 0 | nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction("MWQPusher", [&, k]() { |
122 | 0 | // Give a bit of breathing space to construct other threads. |
123 | 0 | PR_Sleep(PR_MillisecondsToInterval(100)); |
124 | 0 |
|
125 | 0 | for (int i = 0; i < loops; ++i) { |
126 | 0 | if (q.Push(k * threads + i) && aReaderThreads != 0) { |
127 | 0 | // Run a popper task every time we push the last element of a |
128 | 0 | // buffer. |
129 | 0 | array[++readerThread % aReaderThreads]->Dispatch( |
130 | 0 | popper, nsIThread::DISPATCH_NORMAL); |
131 | 0 | } |
132 | 0 | } |
133 | 0 | ++pushThreadsCompleted; |
134 | 0 | }); Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*)::{lambda()#2}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*)::{lambda()#2}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*)::{lambda()#2}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*)::{lambda()#2}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda()#2}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda()#2}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda()#2}::operator()() const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda()#2}::operator()() const |
135 | 0 | nsresult rv = NS_NewNamedThread("MWQThread", getter_AddRefs(t), r); |
136 | 0 | EXPECT_TRUE(NS_SUCCEEDED(rv)); |
137 | 0 | NS_ADDREF(array[k] = t); |
138 | 0 | } |
139 | 0 | } |
140 | 0 |
|
141 | 0 | for (int k = threads - 1; k >= 0; k--) { |
142 | 0 | array[k]->Shutdown(); |
143 | 0 | NS_RELEASE(array[k]); |
144 | 0 | } |
145 | 0 | delete[] array; |
146 | 0 |
|
147 | 0 | // There may be a few more elements that haven't been read yet. |
148 | 0 | q.PopAll([&pops](const int& i) { ++pops; }); Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*)::{lambda(int const&)#1}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*)::{lambda(int const&)#1}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*)::{lambda(int const&)#1}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*)::{lambda(int const&)#1}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda(int const&)#1}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda(int const&)#1}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda(int const&)#1}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda(int const&)#1}::operator()(int const&) const |
149 | 0 | const int pushes = aWriterThreads * loops; |
150 | 0 | EXPECT_EQ(pushes, pops); |
151 | 0 | q.PopAll([](const int& i) { EXPECT_TRUE(false); }); Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*)::{lambda(int const&)#2}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*)::{lambda(int const&)#2}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*)::{lambda(int const&)#2}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*)::{lambda(int const&)#2}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda(int const&)#2}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda(int const&)#2}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda(int const&)#2}::operator()(int const&) const Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda(int const&)#2}::operator()(int const&) const |
152 | 0 |
|
153 | 0 | double duration = mozilla::ToSeconds(mozilla::DDNow()) - start - 0.1; |
154 | 0 | printf("%s threads=%dw+%dr loops/thread=%d pushes=pops=%d duration=%fs " |
155 | 0 | "pushes/s=%f buffers: live=%d (w %d) reusable=%d (w %d) " |
156 | 0 | "alloc=%d (w %d)\n", |
157 | 0 | aPrintPrefix, |
158 | 0 | aWriterThreads, |
159 | 0 | aReaderThreads, |
160 | 0 | loops, |
161 | 0 | pushes, |
162 | 0 | duration, |
163 | 0 | pushes / duration, |
164 | 0 | q.LiveBuffersStats().mCount, |
165 | 0 | q.LiveBuffersStats().mWatermark, |
166 | 0 | q.ReusableBuffersStats().mCount, |
167 | 0 | q.ReusableBuffersStats().mWatermark, |
168 | 0 | q.AllocatedBuffersStats().mCount, |
169 | 0 | q.AllocatedBuffersStats().mWatermark); |
170 | 0 | } Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_None> >(int, int, int, char const*) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 10u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<mozilla::MultiWriterQueue<int, 8192u, mozilla::MultiWriterQueueReaderLocking_Mutex> >(int, int, int, char const*) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*) |
171 | | |
172 | | TEST(MultiWriterQueue, MultiWriterSingleReader) |
173 | 0 | { |
174 | 0 | // Small BufferSize, to exercize the buffer management code. |
175 | 0 | TestMultiWriterQueueMT< |
176 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
177 | 0 | 1, 0, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
178 | 0 | TestMultiWriterQueueMT< |
179 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
180 | 0 | 1, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
181 | 0 | TestMultiWriterQueueMT< |
182 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
183 | 0 | 2, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
184 | 0 | TestMultiWriterQueueMT< |
185 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
186 | 0 | 3, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
187 | 0 | TestMultiWriterQueueMT< |
188 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
189 | 0 | 4, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
190 | 0 | TestMultiWriterQueueMT< |
191 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
192 | 0 | 5, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
193 | 0 | TestMultiWriterQueueMT< |
194 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
195 | 0 | 6, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
196 | 0 | TestMultiWriterQueueMT< |
197 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
198 | 0 | 7, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
199 | 0 | TestMultiWriterQueueMT< |
200 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
201 | 0 | 8, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
202 | 0 | TestMultiWriterQueueMT< |
203 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
204 | 0 | 9, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
205 | 0 | TestMultiWriterQueueMT< |
206 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
207 | 0 | 10, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
208 | 0 | TestMultiWriterQueueMT< |
209 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
210 | 0 | 16, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
211 | 0 | TestMultiWriterQueueMT< |
212 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
213 | 0 | 32, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
214 | 0 | TestMultiWriterQueueMT< |
215 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_None>>( |
216 | 0 | 64, 1, 2 * 1024 * 1024, "MultiWriterQueue<int, 10, Locking_None>"); |
217 | 0 |
|
218 | 0 | // A more real-life buffer size. |
219 | 0 | TestMultiWriterQueueMT<MultiWriterQueue<int, |
220 | 0 | MultiWriterQueueDefaultBufferSize, |
221 | 0 | MultiWriterQueueReaderLocking_None>>( |
222 | 0 | 64, |
223 | 0 | 1, |
224 | 0 | 2 * 1024 * 1024, |
225 | 0 | "MultiWriterQueue<int, DefaultBufferSize, Locking_None>"); |
226 | 0 |
|
227 | 0 | // DEBUG-mode thread-safety checks should make the following (multi-reader |
228 | 0 | // with no locking) crash; uncomment to verify. |
229 | 0 | // TestMultiWriterQueueMT< |
230 | 0 | // MultiWriterQueue<int, MultiWriterQueueDefaultBufferSize, MultiWriterQueueReaderLocking_None>>(64, 2, 2*1024*1024); |
231 | 0 | } |
232 | | |
233 | | TEST(MultiWriterQueue, MultiWriterMultiReader) |
234 | 0 | { |
235 | 0 | static_assert( |
236 | 0 | mozilla::IsSame< |
237 | 0 | MultiWriterQueue<int, 10>, |
238 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>::value, |
239 | 0 | "MultiWriterQueue reader locking should use Mutex by default"); |
240 | 0 |
|
241 | 0 | // Small BufferSize, to exercize the buffer management code. |
242 | 0 | TestMultiWriterQueueMT< |
243 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
244 | 0 | 1, 2, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
245 | 0 | TestMultiWriterQueueMT< |
246 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
247 | 0 | 2, 2, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
248 | 0 | TestMultiWriterQueueMT< |
249 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
250 | 0 | 3, 2, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
251 | 0 | TestMultiWriterQueueMT< |
252 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
253 | 0 | 4, 2, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
254 | 0 | TestMultiWriterQueueMT< |
255 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
256 | 0 | 5, 2, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
257 | 0 | TestMultiWriterQueueMT< |
258 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
259 | 0 | 6, 2, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
260 | 0 | TestMultiWriterQueueMT< |
261 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
262 | 0 | 7, 2, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
263 | 0 | TestMultiWriterQueueMT< |
264 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
265 | 0 | 8, 2, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
266 | 0 | TestMultiWriterQueueMT< |
267 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
268 | 0 | 9, 2, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
269 | 0 | TestMultiWriterQueueMT< |
270 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
271 | 0 | 10, 4, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
272 | 0 | TestMultiWriterQueueMT< |
273 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
274 | 0 | 16, 8, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
275 | 0 | TestMultiWriterQueueMT< |
276 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
277 | 0 | 32, 16, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
278 | 0 | TestMultiWriterQueueMT< |
279 | 0 | MultiWriterQueue<int, 10, MultiWriterQueueReaderLocking_Mutex>>( |
280 | 0 | 64, 32, 1024 * 1024, "MultiWriterQueue<int, 10, Locking_Mutex>"); |
281 | 0 |
|
282 | 0 | // A more real-life buffer size. |
283 | 0 | TestMultiWriterQueueMT<MultiWriterQueue<int, |
284 | 0 | MultiWriterQueueDefaultBufferSize, |
285 | 0 | MultiWriterQueueReaderLocking_Mutex>>( |
286 | 0 | 64, |
287 | 0 | 32, |
288 | 0 | 1024 * 1024, |
289 | 0 | "MultiWriterQueue<int, DefaultBufferSize, Locking_Mutex>"); |
290 | 0 | } |
291 | | |
292 | | // Single-threaded use only. |
293 | | struct DequeWrapperST |
294 | | { |
295 | | nsDeque mDQ; |
296 | | |
297 | | bool Push(int i) |
298 | 0 | { |
299 | 0 | mDQ.PushFront(reinterpret_cast<void*>(static_cast<uintptr_t>(i))); |
300 | 0 | return true; |
301 | 0 | } |
302 | | template<typename F> |
303 | | void PopAll(F&& aF) |
304 | 0 | { |
305 | 0 | while (mDQ.GetSize() != 0) { |
306 | 0 | int i = static_cast<int>(reinterpret_cast<uintptr_t>(mDQ.Pop())); |
307 | 0 | aF(i); |
308 | 0 | } |
309 | 0 | } Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperST::PopAll<void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}>(void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}&&) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperST::PopAll<void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda(int const&)#1}>(void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda(int const&)#1}&&) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperST::PopAll<void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda(int const&)#2}>(void TestMultiWriterQueueMT<DequeWrapperST>(int, int, int, char const*)::{lambda(int const&)#2}&&) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperST::PopAll<void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}>(void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}&&) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperST::PopAll<void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda(int const&)#1}>(void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda(int const&)#1}&&) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperST::PopAll<void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda(int const&)#2}>(void TestMultiWriterQueueMT<DequeWrapperAW>(int, int, int, char const*)::{lambda(int const&)#2}&&) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperST::PopAll<void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}>(void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}&&) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperST::PopAll<void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda(int const&)#1}>(void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda(int const&)#1}&&) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperST::PopAll<void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda(int const&)#2}>(void TestMultiWriterQueueMT<DequeWrapperMW>(int, int, int, char const*)::{lambda(int const&)#2}&&) |
310 | | |
311 | | struct CountAndWatermark |
312 | | { |
313 | | int mCount = 0; |
314 | | int mWatermark = 0; |
315 | | } mLiveBuffersStats, mReusableBuffersStats, mAllocatedBuffersStats; |
316 | | |
317 | 0 | CountAndWatermark LiveBuffersStats() const { return mLiveBuffersStats; } |
318 | | CountAndWatermark ReusableBuffersStats() const |
319 | 0 | { |
320 | 0 | return mReusableBuffersStats; |
321 | 0 | } |
322 | | CountAndWatermark AllocatedBuffersStats() const |
323 | 0 | { |
324 | 0 | return mAllocatedBuffersStats; |
325 | 0 | } |
326 | | }; |
327 | | |
328 | | // Multi-thread (atomic) writes allowed, make sure you don't pop unless writes can't happen. |
329 | | struct DequeWrapperAW : DequeWrapperST |
330 | | { |
331 | | mozilla::Atomic<bool> mWriting{ false }; |
332 | | |
333 | | bool Push(int i) |
334 | 0 | { |
335 | 0 | while (!mWriting.compareExchange(false, true)) { |
336 | 0 | } |
337 | 0 | mDQ.PushFront(reinterpret_cast<void*>(static_cast<uintptr_t>(i))); |
338 | 0 | mWriting = false; |
339 | 0 | return true; |
340 | 0 | } |
341 | | }; |
342 | | |
343 | | // Multi-thread writes allowed, make sure you don't pop unless writes can't happen. |
344 | | struct DequeWrapperMW : DequeWrapperST |
345 | | { |
346 | | mozilla::Mutex mMutex; |
347 | | |
348 | | DequeWrapperMW() |
349 | | : mMutex("DequeWrapperMW/MT") |
350 | 0 | { |
351 | 0 | } |
352 | | |
353 | | bool Push(int i) |
354 | 0 | { |
355 | 0 | mozilla::MutexAutoLock lock(mMutex); |
356 | 0 | mDQ.PushFront(reinterpret_cast<void*>(static_cast<uintptr_t>(i))); |
357 | 0 | return true; |
358 | 0 | } |
359 | | }; |
360 | | |
361 | | // Multi-thread read&writes allowed. |
362 | | struct DequeWrapperMT : DequeWrapperMW |
363 | | { |
364 | | template<typename F> |
365 | | void PopAll(F&& aF) |
366 | 0 | { |
367 | 0 | while (mDQ.GetSize() != 0) { |
368 | 0 | int i; |
369 | 0 | { |
370 | 0 | mozilla::MutexAutoLock lock(mMutex); |
371 | 0 | i = static_cast<int>(reinterpret_cast<uintptr_t>(mDQ.Pop())); |
372 | 0 | } |
373 | 0 | aF(i); |
374 | 0 | } |
375 | 0 | } Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperMT::PopAll<void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}>(void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda()#1}::operator()() const::{lambda(int const&)#1}&&) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperMT::PopAll<void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda(int const&)#1}>(void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda(int const&)#1}&&) Unexecuted instantiation: Unified_cpp_media_doctor_gtest0.cpp:void DequeWrapperMT::PopAll<void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda(int const&)#2}>(void TestMultiWriterQueueMT<DequeWrapperMT>(int, int, int, char const*)::{lambda(int const&)#2}&&) |
376 | | }; |
377 | | |
378 | | TEST(MultiWriterQueue, nsDequeBenchmark) |
379 | 0 | { |
380 | 0 | TestMultiWriterQueueMT<DequeWrapperST>( |
381 | 0 | 1, 0, 2 * 1024 * 1024, "DequeWrapperST "); |
382 | 0 |
|
383 | 0 | TestMultiWriterQueueMT<DequeWrapperAW>( |
384 | 0 | 1, 0, 2 * 1024 * 1024, "DequeWrapperAW "); |
385 | 0 | TestMultiWriterQueueMT<DequeWrapperMW>( |
386 | 0 | 1, 0, 2 * 1024 * 1024, "DequeWrapperMW "); |
387 | 0 | TestMultiWriterQueueMT<DequeWrapperMT>( |
388 | 0 | 1, 0, 2 * 1024 * 1024, "DequeWrapperMT "); |
389 | 0 | TestMultiWriterQueueMT<DequeWrapperMT>( |
390 | 0 | 1, 1, 2 * 1024 * 1024, "DequeWrapperMT "); |
391 | 0 |
|
392 | 0 | TestMultiWriterQueueMT<DequeWrapperAW>( |
393 | 0 | 8, 0, 2 * 1024 * 1024, "DequeWrapperAW "); |
394 | 0 | TestMultiWriterQueueMT<DequeWrapperMW>( |
395 | 0 | 8, 0, 2 * 1024 * 1024, "DequeWrapperMW "); |
396 | 0 | TestMultiWriterQueueMT<DequeWrapperMT>( |
397 | 0 | 8, 0, 2 * 1024 * 1024, "DequeWrapperMT "); |
398 | 0 | TestMultiWriterQueueMT<DequeWrapperMT>( |
399 | 0 | 8, 1, 2 * 1024 * 1024, "DequeWrapperMT "); |
400 | 0 | } |