C++ examples for Thread:Mutex
Using a condition_variable to Wake a Thread
#include <condition_variable> #include <cstdlib> #include <functional> #include <iostream> #include <mutex> #include <thread> #include <stack> #include <vector> using namespace std; class MyObject/*w w w . j a va 2 s . c o m*/ { private: static const unsigned int MAX_OBJECTS{ 8 }; using MyCollection = vector < MyObject >; static MyCollection s_ManagedObjects; static stack<unsigned int> s_FreeList; static mutex s_Mutex; unsigned int m_Value{ 0xFFFFFFFF }; public: MyObject() = default; MyObject(unsigned int value) : m_Value{ value } { } unsigned int GetValue() const { return m_Value; } void* operator new(size_t numBytes) { lock_guard<mutex> lock{ s_Mutex }; void* objectMemory{}; if (s_ManagedObjects.capacity() < MAX_OBJECTS) { s_ManagedObjects.reserve(MAX_OBJECTS); } if (numBytes == sizeof(MyObject) && s_ManagedObjects.size() < s_ManagedObjects.capacity()) { unsigned int index{ 0xFFFFFFFF }; if (s_FreeList.size() > 0) { index = s_FreeList.top(); s_FreeList.pop(); } if (index == 0xFFFFFFFF) { s_ManagedObjects.push_back({}); index = s_ManagedObjects.size() - 1; } objectMemory = s_ManagedObjects.data() + index; } else { objectMemory = malloc(numBytes); } return objectMemory; } void operator delete(void* pMem) { lock_guard<mutex> lock{ s_Mutex }; const intptr_t index{ (static_cast<MyObject*>(pMem)-s_ManagedObjects.data()) / static_cast<intptr_t>(sizeof(MyObject)) }; if (0 <= index && index < static_cast<intptr_t>(s_ManagedObjects.size())) { s_FreeList.emplace(static_cast<unsigned int>(index)); } else { free(pMem); } } }; MyObject::MyCollection MyObject::s_ManagedObjects{}; stack<unsigned int> MyObject::s_FreeList{}; mutex MyObject::s_Mutex; using ProducerQueue = vector < unsigned int > ; void ThreadTask( reference_wrapper<condition_variable> condition, reference_wrapper<mutex> queueMutex, reference_wrapper<ProducerQueue> queueRef, reference_wrapper<bool> die) { ProducerQueue& queue{ queueRef.get() }; while (!die.get() || queue.size()) { unique_lock<mutex> lock{ queueMutex.get() }; function<bool()> predicate{ [&queue]() { return !queue.empty(); } }; condition.get().wait(lock, predicate); unsigned int numberToCreate{ queue.back() }; queue.pop_back(); cout << "Creating " << numberToCreate << " objects on thread " << this_thread::get_id() << endl; for (unsigned int i = 0; i < numberToCreate; ++i) { MyObject* pObject{ new MyObject(i) }; } } } int main(int argc, char* argv[]) { condition_variable condition; mutex queueMutex; ProducerQueue queue; bool die{ false }; thread myThread1{ ThreadTask, ref(condition), ref(queueMutex), ref(queue), ref(die) }; thread myThread2{ ThreadTask, ref(condition), ref(queueMutex), ref(queue), ref(die) }; queueMutex.lock(); queue.emplace_back(300000); queue.emplace_back(400000); queueMutex.unlock(); condition.notify_all(); this_thread::sleep_for( 10ms ); while (!queueMutex.try_lock()) { cout << "Main waiting for queue access!" << endl; this_thread::sleep_for( 100ms ); } queue.emplace_back(100000); queue.emplace_back(200000); this_thread::sleep_for( 1000ms ); condition.notify_one(); this_thread::sleep_for( 1000ms ); condition.notify_one(); this_thread::sleep_for( 1000ms ); queueMutex.unlock(); die = true; cout << "main waiting for join!" << endl; myThread1.join(); myThread2.join(); return 0; }