2 * Copyright (C) 2017 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
28 #include <type_traits>
29 #include <wtf/DataLog.h>
30 #include <wtf/HashSet.h>
32 #include <wtf/ThreadMessage.h>
33 #include <wtf/Vector.h>
34 #include <wtf/threads/Signals.h>
36 static void runThreadMessageTest(unsigned numSenders, unsigned numMessages)
38 Atomic<bool> receiverShouldKeepRunning(true);
39 RefPtr<Thread> receiverThread = Thread::create("ThreadMessage receiver", [&receiverShouldKeepRunning] () {
40 while (receiverShouldKeepRunning.load()) { }
42 ASSERT_TRUE(receiverThread);
44 Vector<RefPtr<Thread>> senderThreads(numSenders);
45 Vector<unsigned> messagesRun(numSenders);
46 Vector<unsigned> handlersRun(numSenders);
50 for (unsigned senderID = 0; senderID < numSenders; ++senderID) {
51 senderThreads[senderID] = Thread::create("ThreadMessage sender", [senderID, numMessages, receiverThread, &messagesRun, &handlersRun] () {
52 for (unsigned i = 0; i < numMessages; ++i) {
53 auto result = sendMessage(*receiverThread.get(), [senderID, &handlersRun] (PlatformRegisters&) {
54 handlersRun[senderID]++;
56 EXPECT_TRUE(result == WTF::MessageStatus::MessageRan);
57 messagesRun[senderID]++;
60 ASSERT_TRUE(senderThreads[senderID]);
63 for (unsigned i = 0; i < numSenders; ++i)
64 senderThreads[i]->waitForCompletion();
66 receiverShouldKeepRunning.store(false);
67 receiverThread->waitForCompletion();
69 for (unsigned i = 0; i < numSenders; ++i) {
70 EXPECT_EQ(numMessages, messagesRun[i]);
71 EXPECT_EQ(numMessages, handlersRun[i]);
75 TEST(ThreadMessage, Basic)
77 runThreadMessageTest(1, 1);
78 runThreadMessageTest(1, 100);
81 TEST(ThreadMessage, MultipleSenders)
83 runThreadMessageTest(10, 1);
84 runThreadMessageTest(10, 100);
85 runThreadMessageTest(10, 10000);
88 class ReflectedThread : public Thread {
90 using Thread::m_mutex;
91 using Thread::m_handle;
92 using Thread::hasExited;
95 TEST(ThreadMessage, SignalsWorkOnExit)
97 static bool handlerRan = false;
98 installSignalHandler(Signal::Usr, [] (Signal, SigInfo&, PlatformRegisters&) -> SignalAction {
101 return SignalAction::Handled;
104 Atomic<bool> receiverShouldKeepRunning(true);
105 RefPtr<Thread> receiverThread = (Thread::create("ThreadMessage receiver",
106 [&receiverShouldKeepRunning] () {
107 while (receiverShouldKeepRunning.load()) { }
109 ASSERT_TRUE(receiverThread);
113 std::unique_lock<std::mutex> locker(static_cast<ReflectedThread*>(receiverThread.get())->m_mutex);
114 receiverShouldKeepRunning.store(false);
115 EXPECT_FALSE(static_cast<ReflectedThread*>(receiverThread.get())->hasExited());
117 signalFired = !pthread_kill(static_cast<ReflectedThread*>(receiverThread.get())->m_handle, toSystemSignal(Signal::Usr));
120 receiverThread->waitForCompletion();
121 EXPECT_TRUE(handlerRan || !signalFired);