testThreadingThread.cpp (3251B)
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 */ 4 /* This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "mozilla/Atomics.h" 9 #include "mozilla/IntegerRange.h" 10 #include "mozilla/Vector.h" 11 12 #include <utility> 13 14 #include "js/AllocPolicy.h" 15 #include "jsapi-tests/tests.h" 16 #include "threading/Thread.h" 17 18 BEGIN_TEST(testThreadingThreadJoin) { 19 bool flag = false; 20 js::Thread thread; 21 CHECK(thread.init([](bool* flagp) { *flagp = true; }, &flag)); 22 CHECK(thread.joinable()); 23 thread.join(); 24 CHECK(flag); 25 CHECK(!thread.joinable()); 26 return true; 27 } 28 END_TEST(testThreadingThreadJoin) 29 30 BEGIN_TEST(testThreadingThreadDetach) { 31 // We are going to detach this thread. Unlike join, we can't have it pointing 32 // at the stack because it might do the write after we have returned and 33 // pushed a new frame. 34 bool* flag = js_new<bool>(false); 35 js::Thread thread; 36 CHECK(thread.init( 37 [](bool* flag) { 38 *flag = true; 39 js_delete(flag); 40 }, 41 std::move(flag))); 42 CHECK(thread.joinable()); 43 thread.detach(); 44 CHECK(!thread.joinable()); 45 46 return true; 47 } 48 END_TEST(testThreadingThreadDetach) 49 50 BEGIN_TEST(testThreadingThreadSetName) { 51 js::Thread thread; 52 CHECK(thread.init([]() { js::ThisThread::SetName("JSAPI Test Thread"); })); 53 thread.detach(); 54 return true; 55 } 56 END_TEST(testThreadingThreadSetName) 57 58 BEGIN_TEST(testThreadingThreadId) { 59 CHECK(js::ThreadId() == js::ThreadId()); 60 js::ThreadId fromOther; 61 js::Thread thread; 62 CHECK(thread.init( 63 [](js::ThreadId* idp) { *idp = js::ThreadId::ThisThreadId(); }, 64 &fromOther)); 65 js::ThreadId fromMain = thread.get_id(); 66 thread.join(); 67 CHECK(fromOther == fromMain); 68 return true; 69 } 70 END_TEST(testThreadingThreadId) 71 72 BEGIN_TEST(testThreadingThreadVectorMoveConstruct) { 73 const static size_t N = 10; 74 mozilla::Atomic<int> count(0); 75 mozilla::Vector<js::Thread, 0, js::SystemAllocPolicy> v; 76 for (auto i : mozilla::IntegerRange(N)) { 77 CHECK(v.emplaceBack()); 78 CHECK(v.back().init([](mozilla::Atomic<int>* countp) { (*countp)++; }, 79 &count)); 80 CHECK(v.length() == i + 1); 81 } 82 for (auto& th : v) { 83 th.join(); 84 } 85 CHECK(count == 10); 86 return true; 87 } 88 END_TEST(testThreadingThreadVectorMoveConstruct) 89 90 // This test is checking that args are using "decay" copy, per spec. If we do 91 // not use decay copy properly, the rvalue reference |bool&& b| in the 92 // constructor will automatically become an lvalue reference |bool& b| in the 93 // trampoline, causing us to read through the reference when passing |bool bb| 94 // from the trampoline. If the parent runs before the child, the bool may have 95 // already become false, causing the trampoline to read the changed value, thus 96 // causing the child's assertion to fail. 97 BEGIN_TEST(testThreadingThreadArgCopy) { 98 for (size_t i = 0; i < 10000; ++i) { 99 bool b = true; 100 js::Thread thread; 101 CHECK(thread.init([](bool bb) { MOZ_RELEASE_ASSERT(bb); }, b)); 102 b = false; 103 thread.join(); 104 } 105 return true; 106 } 107 END_TEST(testThreadingThreadArgCopy)