diff options
Diffstat (limited to 'js/src/jsapi-tests/testThreadingThread.cpp')
-rw-r--r-- | js/src/jsapi-tests/testThreadingThread.cpp | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/js/src/jsapi-tests/testThreadingThread.cpp b/js/src/jsapi-tests/testThreadingThread.cpp new file mode 100644 index 0000000000..68a7a388b0 --- /dev/null +++ b/js/src/jsapi-tests/testThreadingThread.cpp @@ -0,0 +1,107 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: set ts=8 sts=2 et sw=2 tw=80: + */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/Atomics.h" +#include "mozilla/IntegerRange.h" +#include "mozilla/Vector.h" + +#include <utility> + +#include "js/AllocPolicy.h" +#include "jsapi-tests/tests.h" +#include "threading/Thread.h" + +BEGIN_TEST(testThreadingThreadJoin) { + bool flag = false; + js::Thread thread; + CHECK(thread.init([](bool* flagp) { *flagp = true; }, &flag)); + CHECK(thread.joinable()); + thread.join(); + CHECK(flag); + CHECK(!thread.joinable()); + return true; +} +END_TEST(testThreadingThreadJoin) + +BEGIN_TEST(testThreadingThreadDetach) { + // We are going to detach this thread. Unlike join, we can't have it pointing + // at the stack because it might do the write after we have returned and + // pushed a new frame. + bool* flag = js_new<bool>(false); + js::Thread thread; + CHECK(thread.init( + [](bool* flag) { + *flag = true; + js_delete(flag); + }, + std::move(flag))); + CHECK(thread.joinable()); + thread.detach(); + CHECK(!thread.joinable()); + + return true; +} +END_TEST(testThreadingThreadDetach) + +BEGIN_TEST(testThreadingThreadSetName) { + js::Thread thread; + CHECK(thread.init([]() { js::ThisThread::SetName("JSAPI Test Thread"); })); + thread.detach(); + return true; +} +END_TEST(testThreadingThreadSetName) + +BEGIN_TEST(testThreadingThreadId) { + CHECK(js::ThreadId() == js::ThreadId()); + js::ThreadId fromOther; + js::Thread thread; + CHECK(thread.init( + [](js::ThreadId* idp) { *idp = js::ThreadId::ThisThreadId(); }, + &fromOther)); + js::ThreadId fromMain = thread.get_id(); + thread.join(); + CHECK(fromOther == fromMain); + return true; +} +END_TEST(testThreadingThreadId) + +BEGIN_TEST(testThreadingThreadVectorMoveConstruct) { + const static size_t N = 10; + mozilla::Atomic<int> count(0); + mozilla::Vector<js::Thread, 0, js::SystemAllocPolicy> v; + for (auto i : mozilla::IntegerRange(N)) { + CHECK(v.emplaceBack()); + CHECK(v.back().init([](mozilla::Atomic<int>* countp) { (*countp)++; }, + &count)); + CHECK(v.length() == i + 1); + } + for (auto& th : v) { + th.join(); + } + CHECK(count == 10); + return true; +} +END_TEST(testThreadingThreadVectorMoveConstruct) + +// This test is checking that args are using "decay" copy, per spec. If we do +// not use decay copy properly, the rvalue reference |bool&& b| in the +// constructor will automatically become an lvalue reference |bool& b| in the +// trampoline, causing us to read through the reference when passing |bool bb| +// from the trampoline. If the parent runs before the child, the bool may have +// already become false, causing the trampoline to read the changed value, thus +// causing the child's assertion to fail. +BEGIN_TEST(testThreadingThreadArgCopy) { + for (size_t i = 0; i < 10000; ++i) { + bool b = true; + js::Thread thread; + CHECK(thread.init([](bool bb) { MOZ_RELEASE_ASSERT(bb); }, b)); + b = false; + thread.join(); + } + return true; +} +END_TEST(testThreadingThreadArgCopy) |