testThreadingExclusiveData.cpp (2315B)
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 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/IntegerRange.h" 8 #include "js/Vector.h" 9 #include "jsapi-tests/tests.h" 10 #include "threading/ExclusiveData.h" 11 #include "threading/Thread.h" 12 13 // One thread for each bit in our counter. 14 const static uint8_t NumThreads = 64; 15 const static bool ShowDiagnostics = false; 16 17 struct CounterAndBit { 18 uint8_t bit; 19 const js::ExclusiveData<uint64_t>& counter; 20 21 CounterAndBit(uint8_t bit, const js::ExclusiveData<uint64_t>& counter) 22 : bit(bit), counter(counter) { 23 MOZ_ASSERT(bit < NumThreads); 24 } 25 }; 26 27 void printDiagnosticMessage(uint8_t bit, uint64_t seen) { 28 if (!ShowDiagnostics) { 29 return; 30 } 31 32 fprintf(stderr, "Thread %d saw ", bit); 33 for (auto i : mozilla::IntegerRange(NumThreads)) { 34 if (seen & (uint64_t(1) << i)) { 35 fprintf(stderr, "1"); 36 } else { 37 fprintf(stderr, "0"); 38 } 39 } 40 fprintf(stderr, "\n"); 41 } 42 43 void setBitAndCheck(CounterAndBit* counterAndBit) { 44 while (true) { 45 { 46 // Set our bit. Repeatedly setting it is idempotent. 47 auto guard = counterAndBit->counter.lock(); 48 printDiagnosticMessage(counterAndBit->bit, guard); 49 guard |= (uint64_t(1) << counterAndBit->bit); 50 } 51 52 { 53 // Check to see if we have observed all the other threads setting 54 // their bit as well. 55 auto guard = counterAndBit->counter.lock(); 56 printDiagnosticMessage(counterAndBit->bit, guard); 57 if (guard == UINT64_MAX) { 58 js_delete(counterAndBit); 59 return; 60 } 61 } 62 } 63 } 64 65 BEGIN_TEST(testExclusiveData) { 66 js::ExclusiveData<uint64_t> counter(js::mutexid::TestMutex, 0); 67 68 js::Vector<js::Thread> threads(cx); 69 CHECK(threads.reserve(NumThreads)); 70 71 for (auto i : mozilla::IntegerRange(NumThreads)) { 72 auto counterAndBit = js_new<CounterAndBit>(i, counter); 73 CHECK(counterAndBit); 74 CHECK(threads.emplaceBack()); 75 CHECK(threads.back().init(setBitAndCheck, counterAndBit)); 76 } 77 78 for (auto& thread : threads) { 79 thread.join(); 80 } 81 82 return true; 83 } 84 END_TEST(testExclusiveData)