Diff
Modified: trunk/Source/WTF/ChangeLog (207155 => 207156)
--- trunk/Source/WTF/ChangeLog 2016-10-11 19:29:47 UTC (rev 207155)
+++ trunk/Source/WTF/ChangeLog 2016-10-11 19:35:36 UTC (rev 207156)
@@ -1,3 +1,26 @@
+2016-10-11 Said Abou-Hallawa <[email protected]>
+
+ Add SynchronizedFixedQueue class
+ https://bugs.webkit.org/show_bug.cgi?id=162478
+
+ Reviewed by Geoffrey Garen.
+
+ This class represents a simple producer/consumer worker. It facilitates
+ synchronizing enqueuing to and dequeuing from a fixed size-queue. It uses
+ a single lock and a single condition to synchronize all its members among
+ the working threads. This means a single thread is active at any time and
+ and the other threads are blocked waiting for the lock to be released. Or
+ they are sleeping waiting for the condition to be satisfied.
+
+ * WTF.xcodeproj/project.pbxproj:
+ * wtf/SynchronizedFixedQueue.h: Added.
+ (WTF::SynchronizedFixedQueue::SynchronizedFixedQueue):
+ (WTF::SynchronizedFixedQueue::open): Restore the queue to its original state.
+ (WTF::SynchronizedFixedQueue::close): Wake all the sleeping threads with a closing state.
+ (WTF::SynchronizedFixedQueue::isOpen): Does the queue accept new items?
+ (WTF::SynchronizedFixedQueue::enqueue): Enqueue an item into the queue.
+ (WTF::SynchronizedFixedQueue::dequeue): Dequeue an item form the queue.
+
2016-10-11 Alex Christensen <[email protected]>
Remove dead networking code
Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (207155 => 207156)
--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj 2016-10-11 19:29:47 UTC (rev 207155)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj 2016-10-11 19:35:36 UTC (rev 207156)
@@ -119,6 +119,7 @@
515F79561CFD3A6900CCED93 /* CrossThreadQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 515F79551CFD3A6900CCED93 /* CrossThreadQueue.h */; };
539EB0631D55284200C82EF7 /* LEBDecoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 539EB0621D55284200C82EF7 /* LEBDecoder.h */; };
553071CA1C40427200384898 /* TinyLRUCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 553071C91C40427200384898 /* TinyLRUCache.h */; };
+ 5597F82F1D94B9970066BC21 /* SynchronizedFixedQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 5597F82C1D94B9970066BC21 /* SynchronizedFixedQueue.h */; };
5C7C88D41D0A3A0A009D2F6D /* UniqueRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 5C7C88D31D0A3A0A009D2F6D /* UniqueRef.h */; };
70A993FE1AD7151300FA615B /* SymbolRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 70A993FC1AD7151300FA615B /* SymbolRegistry.cpp */; };
70A993FF1AD7151300FA615B /* SymbolRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 70A993FD1AD7151300FA615B /* SymbolRegistry.h */; };
@@ -463,6 +464,7 @@
515F79551CFD3A6900CCED93 /* CrossThreadQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossThreadQueue.h; sourceTree = "<group>"; };
539EB0621D55284200C82EF7 /* LEBDecoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LEBDecoder.h; sourceTree = "<group>"; };
553071C91C40427200384898 /* TinyLRUCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyLRUCache.h; sourceTree = "<group>"; };
+ 5597F82C1D94B9970066BC21 /* SynchronizedFixedQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SynchronizedFixedQueue.h; sourceTree = "<group>"; };
5B43383A5D0B463C9433D933 /* IndexMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IndexMap.h; sourceTree = "<group>"; };
5C7C88D31D0A3A0A009D2F6D /* UniqueRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UniqueRef.h; sourceTree = "<group>"; };
5D247B6214689B8600E78B76 /* libWTF.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libWTF.a; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1023,6 +1025,7 @@
A748745117A0BDAE00FA04CB /* StringHashDumpContext.h */,
0FDDBFA51666DFA300C55FEF /* StringPrintStream.cpp */,
0FDDBFA61666DFA300C55FEF /* StringPrintStream.h */,
+ 5597F82C1D94B9970066BC21 /* SynchronizedFixedQueue.h */,
0FB317C31C488001007E395A /* SystemTracing.h */,
A8A4731A151A825B004123FF /* TemporaryChange.h */,
A8A4732F151A825B004123FF /* ThreadFunctionInvocation.h */,
@@ -1407,6 +1410,7 @@
C4F8A93719C65EB400B2B15D /* Stopwatch.h in Headers */,
1A6BB769162F300500DD16DB /* StreamBuffer.h in Headers */,
A8A4743B151A825B004123FF /* StringBuffer.h in Headers */,
+ 5597F82F1D94B9970066BC21 /* SynchronizedFixedQueue.h in Headers */,
A8A4743D151A825B004123FF /* StringBuilder.h in Headers */,
430B47891AAAAC1A001223DA /* StringCommon.h in Headers */,
A8A4743E151A825B004123FF /* StringConcatenate.h in Headers */,
Added: trunk/Source/WTF/wtf/SynchronizedFixedQueue.h (0 => 207156)
--- trunk/Source/WTF/wtf/SynchronizedFixedQueue.h (rev 0)
+++ trunk/Source/WTF/wtf/SynchronizedFixedQueue.h 2016-10-11 19:35:36 UTC (rev 207156)
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Condition.h>
+#include <wtf/Deque.h>
+#include <wtf/HashSet.h>
+#include <wtf/Lock.h>
+#include <wtf/Locker.h>
+
+namespace WTF {
+
+template<typename T, size_t BufferSize>
+class SynchronizedFixedQueue {
+public:
+ SynchronizedFixedQueue()
+ {
+ static_assert(!((BufferSize - 1) & BufferSize), "BufferSize must be power of 2.");
+ }
+
+ void open()
+ {
+ LockHolder lockHolder(m_mutex);
+ if (m_open)
+ return;
+
+ // Restore the queue to its original state.
+ m_open = true;
+ m_queue.clear();
+ }
+
+ void close()
+ {
+ LockHolder lockHolder(m_mutex);
+ if (!m_open)
+ return;
+
+ // Wake all the sleeping threads up with a closing state.
+ m_open = false;
+ m_condition.notifyAll();
+ }
+
+ bool isOpen()
+ {
+ LockHolder lockHolder(m_mutex);
+ return m_open;
+ }
+
+ bool enqueue(const T& value)
+ {
+ LockHolder lockHolder(m_mutex);
+
+ // Wait for an empty place to be available in the queue.
+ m_condition.wait(m_mutex, [this]() { return !m_open || m_queue.size() < BufferSize; });
+
+ // The queue is closing, exit immediately.
+ if (!m_open)
+ return false;
+
+ // Add the item in the queue.
+ m_queue.append(value);
+
+ // Notify the other threads that an item was added to the queue.
+ m_condition.notifyAll();
+ return true;
+ }
+
+ bool dequeue(T& value)
+ {
+ LockHolder lockHolder(m_mutex);
+
+ // Wait for an item to be added.
+ m_condition.wait(m_mutex, [this]() { return !m_open || m_queue.size(); });
+
+ // The queue is closing, exit immediately.
+ if (!m_open)
+ return false;
+
+ // Get a copy from m_queue.first and then remove it.
+ value = m_queue.first();
+ m_queue.removeFirst();
+
+ // Notify the other threads that an item was removed from the queue.
+ m_condition.notifyAll();
+ return true;
+ }
+
+private:
+ Lock m_mutex;
+ Condition m_condition;
+
+ bool m_open { true };
+ Deque<T, BufferSize> m_queue;
+};
+
+}
+
+using WTF::SynchronizedFixedQueue;
Modified: trunk/Tools/ChangeLog (207155 => 207156)
--- trunk/Tools/ChangeLog 2016-10-11 19:29:47 UTC (rev 207155)
+++ trunk/Tools/ChangeLog 2016-10-11 19:35:36 UTC (rev 207156)
@@ -1,3 +1,40 @@
+2016-10-11 Said Abou-Hallawa <[email protected]>
+
+ Add SynchronizedFixedQueue class
+ https://bugs.webkit.org/show_bug.cgi?id=162478
+
+ Reviewed by Geoffrey Garen.
+
+ Add a new test for SynchronizedFixedQueue. The test defines a new class
+ called ToUpperConverter which converts strings from lower case to upper
+ case. It creates two threads : (1) produce thread and (2) consume thread.
+ Here is what each thread does:
+
+ 1. Main threads: Enqueues lower case strings into m_lowerQueue.
+ 2. Produce thread: Dequeues lower case strings from m_lowerQueue and
+ enqueue their upper case strings in the m_upperQueue.
+ 3. Consume thread: Dequeues upper case strings from m_upperQueue.
+
+ * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+ * TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp: Added.
+ (TestWebKitAPI::textItem): A helper function which returns a lower case string given an index.
+ (TestWebKitAPI::toUpper): A helper function which Returns the upper case of a string.
+ (TestWebKitAPI::ToUpperConverter::ToUpperConverter):
+ (TestWebKitAPI::ToUpperConverter::produceQueue): Returns a workQueue for the produce thread.
+ (TestWebKitAPI::ToUpperConverter::consumeQueue): Returns a workQueue for the consume thread.
+ (TestWebKitAPI::ToUpperConverter::startProducing): Creates a thread for the producer.
+ (TestWebKitAPI::ToUpperConverter::startConsuming): Creates a thread for the consumer.
+ (TestWebKitAPI::ToUpperConverter::start): Starts both the producer and the consumer threads.
+ (TestWebKitAPI::ToUpperConverter::stopProducing): Terminates the producer thread.
+ (TestWebKitAPI::ToUpperConverter::stopConsuming): Terminates the consumer thread.
+ (TestWebKitAPI::ToUpperConverter::stop): Terminates both the producer and the consumer threads.
+ (TestWebKitAPI::ToUpperConverter::enqueueLower): Adds a lower case string to the m_lowerQueue on the main thread.
+ (TestWebKitAPI::ToUpperConverter::isProducing): Returns whether the producing thread is active.
+ (TestWebKitAPI::ToUpperConverter::isConsuming): Returns whether the consuming thread is active.
+ (TestWebKitAPI::ToUpperConverter::produceCount): Returns the number of produced elements.
+ (TestWebKitAPI::ToUpperConverter::consumeCount): Returns the number of consumed elements.
+ (TestWebKitAPI::TEST):
+
2016-10-11 Megan Gardner <[email protected]>
Extend event stream to include interpolated events and add a force press test that uses that interpolation
Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (207155 => 207156)
--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2016-10-11 19:29:47 UTC (rev 207155)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj 2016-10-11 19:35:36 UTC (rev 207156)
@@ -140,6 +140,7 @@
52E5CE4914D21EAB003B2BD8 /* ParentFrame_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52E5CE4814D21EAB003B2BD8 /* ParentFrame_Bundle.cpp */; };
536770341CC8022800D425B1 /* WebScriptObjectDescription.mm in Sources */ = {isa = PBXBuildFile; fileRef = 536770331CC8022800D425B1 /* WebScriptObjectDescription.mm */; };
536770361CC81B6100D425B1 /* WebScriptObjectDescription.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 536770351CC812F900D425B1 /* WebScriptObjectDescription.html */; };
+ 5597F8361D9596C80066BC21 /* SynchronizedFixedQueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5597F8341D9596C80066BC21 /* SynchronizedFixedQueue.cpp */; };
5714ECB91CA8B5B000051AC8 /* DownloadRequestOriginalURL.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5714ECB81CA8B58800051AC8 /* DownloadRequestOriginalURL.html */; };
5714ECBB1CA8BFE400051AC8 /* DownloadRequestOriginalURLFrame.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5714ECBA1CA8BFD100051AC8 /* DownloadRequestOriginalURLFrame.html */; };
5714ECBD1CA8C22A00051AC8 /* DownloadRequestOriginalURL2.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 5714ECBC1CA8C21800051AC8 /* DownloadRequestOriginalURL2.html */; };
@@ -916,6 +917,7 @@
52E5CE4814D21EAB003B2BD8 /* ParentFrame_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParentFrame_Bundle.cpp; sourceTree = "<group>"; };
536770331CC8022800D425B1 /* WebScriptObjectDescription.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebScriptObjectDescription.mm; sourceTree = "<group>"; };
536770351CC812F900D425B1 /* WebScriptObjectDescription.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = WebScriptObjectDescription.html; sourceTree = "<group>"; };
+ 5597F8341D9596C80066BC21 /* SynchronizedFixedQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SynchronizedFixedQueue.cpp; sourceTree = "<group>"; };
5714ECB81CA8B58800051AC8 /* DownloadRequestOriginalURL.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = DownloadRequestOriginalURL.html; sourceTree = "<group>"; };
5714ECBA1CA8BFD100051AC8 /* DownloadRequestOriginalURLFrame.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = DownloadRequestOriginalURLFrame.html; sourceTree = "<group>"; };
5714ECBC1CA8C21800051AC8 /* DownloadRequestOriginalURL2.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = DownloadRequestOriginalURL2.html; sourceTree = "<group>"; };
@@ -1795,6 +1797,7 @@
26F1B44315CA434F00D1E4BF /* StringImpl.cpp */,
C01363C713C3997300EF3964 /* StringOperators.cpp */,
7C74D42D188228F300E5ED57 /* StringView.cpp */,
+ 5597F8341D9596C80066BC21 /* SynchronizedFixedQueue.cpp */,
0BCD85691485C98B00EA2003 /* TemporaryChange.cpp */,
5C5E633D1D0B67940085A025 /* UniqueRef.cpp */,
7CD0D5AA1D5534DE000CC9E1 /* Variant.cpp */,
@@ -2289,6 +2292,7 @@
7C83DF361D0A590C00FEBCF3 /* StringHasher.cpp in Sources */,
7C83DF371D0A590C00FEBCF3 /* StringImpl.cpp in Sources */,
7C83DF381D0A590C00FEBCF3 /* StringOperators.cpp in Sources */,
+ 5597F8361D9596C80066BC21 /* SynchronizedFixedQueue.cpp in Sources */,
7C83DF3A1D0A590C00FEBCF3 /* StringView.cpp in Sources */,
7C83DF3D1D0A590C00FEBCF3 /* TemporaryChange.cpp in Sources */,
7C83DF401D0A590C00FEBCF3 /* TestsController.cpp in Sources */,
Added: trunk/Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp (0 => 207156)
--- trunk/Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp 2016-10-11 19:35:36 UTC (rev 207156)
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <chrono>
+#include <thread>
+
+#include <wtf/ASCIICType.h>
+#include <wtf/SynchronizedFixedQueue.h>
+#include <wtf/WorkQueue.h>
+#include <wtf/text/CString.h>
+#include <wtf/threads/BinarySemaphore.h>
+
+namespace TestWebKitAPI {
+
+static char const* textItem(size_t index)
+{
+ static char const* items[] = { "first", "second", "third", "fourth", "fifth", "sixth" };
+ return index < sizeof(items) / sizeof(items[0]) ? items[index] : nullptr;
+}
+
+static CString toUpper(const CString& lower)
+{
+ CString upper = lower;
+
+ for (char* buffer = upper.mutableData(); *buffer; ++buffer)
+ *buffer = toASCIIUpper(*buffer);
+
+ return upper;
+}
+
+template <size_t BufferSize>
+class ToUpperConverter {
+public:
+ ToUpperConverter()
+ {
+ }
+
+ WorkQueue* produceQueue()
+ {
+ if (!m_produceQueue)
+ m_produceQueue = WorkQueue::create("org.webkit.Produce");
+ return m_produceQueue.get();
+ }
+
+ WorkQueue* consumeQueue()
+ {
+ if (!m_consumeQueue)
+ m_consumeQueue = WorkQueue::create("org.webkit.Consume");
+ return m_consumeQueue.get();
+ }
+
+ void startProducing()
+ {
+ if (isProducing())
+ return;
+
+ produceQueue()->dispatch([this] {
+ CString lower;
+ while (m_lowerQueue.dequeue(lower)) {
+ m_upperQueue.enqueue(toUpper(lower));
+ EXPECT_TRUE(lower == textItem(m_produceCount++));
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
+ }
+ m_produceCloseSemaphore.signal();
+ });
+ }
+
+ void startConsuming()
+ {
+ if (isConsuming())
+ return;
+
+ consumeQueue()->dispatch([this] {
+ CString upper;
+ while (m_upperQueue.dequeue(upper)) {
+ EXPECT_TRUE(upper == toUpper(textItem(m_consumeCount++)));
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ }
+ m_consumeCloseSemaphore.signal();
+ });
+ }
+
+ void start()
+ {
+ startProducing();
+ startConsuming();
+ }
+
+ void stopProducing()
+ {
+ if (!isProducing())
+ return;
+
+ m_lowerQueue.close();
+ m_produceCloseSemaphore.wait(std::numeric_limits<double>::max());
+ m_produceQueue = nullptr;
+ }
+
+ void stopConsuming()
+ {
+ if (!isConsuming())
+ return;
+
+ m_upperQueue.close();
+ m_consumeCloseSemaphore.wait(std::numeric_limits<double>::max());
+ m_consumeQueue = nullptr;
+ }
+
+ void stop()
+ {
+ stopProducing();
+ stopConsuming();
+ }
+
+ void enqueueLower(const CString& lower)
+ {
+ m_lowerQueue.enqueue(lower);
+ }
+
+ bool isProducing() { return m_produceQueue; }
+ bool isConsuming() { return m_consumeQueue; }
+
+ size_t produceCount() const { return m_produceCount; }
+ size_t consumeCount() const { return m_consumeCount; }
+
+private:
+ SynchronizedFixedQueue<CString, BufferSize> m_lowerQueue;
+ SynchronizedFixedQueue<CString, BufferSize> m_upperQueue;
+ RefPtr<WorkQueue> m_produceQueue;
+ RefPtr<WorkQueue> m_consumeQueue;
+ BinarySemaphore m_produceCloseSemaphore;
+ BinarySemaphore m_consumeCloseSemaphore;
+ size_t m_produceCount { 0 };
+ size_t m_consumeCount { 0 };
+};
+
+TEST(WTF_SynchronizedFixedQueue, Basic)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.start();
+ EXPECT_TRUE(converter.isProducing() && converter.isConsuming());
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+
+ EXPECT_EQ(converter.produceCount(), 0U);
+ EXPECT_EQ(converter.consumeCount(), 0U);
+}
+
+TEST(WTF_SynchronizedFixedQueue, ProduceOnly)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.startProducing();
+ EXPECT_TRUE(converter.isProducing() && !converter.isConsuming());
+
+ size_t count = 0;
+ while (char const* item = textItem(count)) {
+ converter.enqueueLower(item);
+ ++count;
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+}
+
+TEST(WTF_SynchronizedFixedQueue, ConsumeOnly)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.startConsuming();
+ EXPECT_TRUE(!converter.isProducing() && converter.isConsuming());
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+}
+
+TEST(WTF_SynchronizedFixedQueue, Limits)
+{
+ ToUpperConverter<4U> converter;
+
+ converter.start();
+ EXPECT_TRUE(converter.isProducing() && converter.isConsuming());
+
+ size_t count = 0;
+ while (char const* item = textItem(count)) {
+ converter.enqueueLower(item);
+ ++count;
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(400));
+
+ converter.stop();
+ EXPECT_FALSE(converter.isProducing() || converter.isConsuming());
+
+ EXPECT_EQ(converter.produceCount(), count);
+ EXPECT_EQ(converter.consumeCount(), count);
+}
+
+}