Last active
May 20, 2016 20:24
-
-
Save vittorioromeo/8c32d9f6c9bcc6389e2dc203ec415f32 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <atomic> | |
#include "./blockingconcurrentqueue.h" | |
using namespace std::chrono_literals; | |
// global counter | |
// * the program can exit when it reaches 1000 | |
// * incremented by tasks | |
std::atomic<int> ctr{0}; | |
// task | |
// * non-copyable | |
// * increments `ctr` on construction | |
// * transfers some mock state `x` on moves | |
struct task | |
{ | |
int x = 0; | |
task() | |
{ | |
++ctr; | |
} | |
task(const task&) = delete; | |
task& operator=(const task&) = delete; | |
task(task&& rhs) : x{rhs.x} | |
{ | |
} | |
task& operator=(task&& rhs) | |
{ | |
x = rhs.x; | |
return *this; | |
} | |
}; | |
// task queue | |
moodycamel::BlockingConcurrentQueue<task> q; | |
// worker | |
// * contains thread that constantly calls `wait_dequeue` | |
// * on dtor, spawns tasks until thread is joined | |
struct worker | |
{ | |
std::thread th; | |
std::atomic<bool> running{true}; | |
std::atomic<bool> exited{false}; | |
worker() | |
{ | |
th = std::thread([this] | |
{ | |
task t; | |
while(running) | |
{ | |
q.wait_dequeue(t); | |
} | |
exited = true; | |
}); | |
} | |
~worker() | |
{ | |
running = false; | |
while(!exited) | |
{ | |
q.enqueue(task{}); | |
std::this_thread::sleep_for(1ms); | |
} | |
th.join(); | |
} | |
}; | |
int main() | |
{ | |
// create 8 workers | |
std::array<worker, 8> ws; | |
// enqueue 1000 tasks | |
for(int i = 0; i < 1000; ++i) | |
{ | |
q.enqueue(task{}); | |
} | |
// wait for `ctr` to be `>= 1000` | |
while(ctr < 1000) | |
{ | |
std::this_thread::sleep_for(1ms); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
WARNING: ThreadSanitizer: data race (pid=15381) | |
Read of size 4 at 0x7d340000cf48 by thread T7: | |
#0 task::operator=(task&&) <null> (a.out+0x000000402c36) | |
#1 bool moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::ImplicitProducer::dequeue<task>(task&) <null> (a.out+0x000000406279) | |
#2 bool moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::ProducerBase::dequeue<task>(task&) <null> (a.out+0x000000405340) | |
#3 bool moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::try_dequeue<task>(task&) <null> (a.out+0x0000004044e9) | |
#4 void moodycamel::BlockingConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::wait_dequeue<task>(task&) <null> (a.out+0x000000403303) | |
#5 worker::worker()::{lambda()#1}::operator()() const <null> (a.out+0x000000402ce6) | |
#6 void std::_Bind_simple<worker::worker()::{lambda()#1} ()>::_M_invoke<>(std::_Index_tuple<>) <null> (a.out+0x00000040a1a4) | |
#7 std::_Bind_simple<worker::worker()::{lambda()#1} ()>::operator()() <null> (a.out+0x00000040a0dd) | |
#8 std::thread::_State_impl<std::_Bind_simple<worker::worker()::{lambda()#1} ()> >::_M_run() <null> (a.out+0x00000040a018) | |
#9 execute_native_thread_routine /build/gcc-multilib/src/gcc/libstdc++-v3/src/c++11/thread.cc:83 (libstdc++.so.6+0x0000000baaae) | |
Previous write of size 8 at 0x7d340000cf48 by main thread: | |
#0 malloc /build/gcc-multilib/src/gcc/libsanitizer/tsan/tsan_interceptors.cc:538 (libtsan.so.0+0x000000026aac) | |
#1 moodycamel::ConcurrentQueueDefaultTraits::malloc(unsigned long) <null> (a.out+0x000000402102) | |
#2 moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::Block* moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::create<moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::Block>() <null> (a.out+0x00000040880b) | |
#3 moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::Block* moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::requisition_block<(moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::AllocationMode)0>() <null> (a.out+0x000000407add) | |
#4 bool moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::ImplicitProducer::enqueue<(moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::AllocationMode)0, task>(task&&) <null> (a.out+0x000000406ed4) | |
#5 bool moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::inner_enqueue<(moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::AllocationMode)0, task>(task&&) <null> (a.out+0x0000004057eb) | |
#6 moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::enqueue(task&&) <null> (a.out+0x0000004049c6) | |
#7 moodycamel::BlockingConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::enqueue(task&&) <null> (a.out+0x00000040343e) | |
#8 main <null> (a.out+0x0000004016dd) | |
Location is heap block of size 208 at 0x7d340000cf30 allocated by main thread: | |
#0 malloc /build/gcc-multilib/src/gcc/libsanitizer/tsan/tsan_interceptors.cc:538 (libtsan.so.0+0x000000026aac) | |
#1 moodycamel::ConcurrentQueueDefaultTraits::malloc(unsigned long) <null> (a.out+0x000000402102) | |
#2 moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::Block* moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::create<moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::Block>() <null> (a.out+0x00000040880b) | |
#3 moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::Block* moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::requisition_block<(moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::AllocationMode)0>() <null> (a.out+0x000000407add) | |
#4 bool moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::ImplicitProducer::enqueue<(moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::AllocationMode)0, task>(task&&) <null> (a.out+0x000000406ed4) | |
#5 bool moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::inner_enqueue<(moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::AllocationMode)0, task>(task&&) <null> (a.out+0x0000004057eb) | |
#6 moodycamel::ConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::enqueue(task&&) <null> (a.out+0x0000004049c6) | |
#7 moodycamel::BlockingConcurrentQueue<task, moodycamel::ConcurrentQueueDefaultTraits>::enqueue(task&&) <null> (a.out+0x00000040343e) | |
#8 main <null> (a.out+0x0000004016dd) | |
Thread T7 (tid=15389, running) created by main thread at: | |
#0 pthread_create /build/gcc-multilib/src/gcc/libsanitizer/tsan/tsan_interceptors.cc:876 (libtsan.so.0+0x000000028360) | |
#1 __gthread_create /build/gcc-multilib/src/gcc-build/x86_64-pc-linux-gnu/libstdc++-v3/include/x86_64-pc-linux-gnu/bits/gthr-default.h:662 (libstdc++.so.6+0x0000000badc4) | |
#2 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) /build/gcc-multilib/src/gcc/libstdc++-v3/src/c++11/thread.cc:163 (libstdc++.so.6+0x0000000badc4) | |
#3 worker::worker() <null> (a.out+0x000000402da3) | |
#4 std::array<worker, 8ul>::array() <null> (a.out+0x000000402f80) | |
#5 main <null> (a.out+0x0000004016b0) | |
SUMMARY: ThreadSanitizer: data race (a.out+0x402c36) in task::operator=(task&&) | |
================== |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment