git.s-ol.nu ~forks/DiligentCore / 1b12c21
Some improvement to ThreadingTools::Signal assiduous 7 months ago
1 changed file(s) with 18 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
4040 public:
4141 Signal()
4242 {
43 m_SignaledValue = 0;
44 m_NumThreadsAwaken = 0;
43 m_SignaledValue.store(0);
44 m_NumThreadsAwaken.store(0);
4545 }
4646
4747 // http://en.cppreference.com/w/cpp/thread/condition_variable
5757 // std::condition_variable works only with std::unique_lock<std::mutex>
5858 std::lock_guard<std::mutex> Lock{m_Mutex};
5959 VERIFY(SignalValue != 0, "Signal value must not be 0");
60 VERIFY(m_SignaledValue == 0 && m_NumThreadsAwaken == 0, "Not all threads have been awaken since the signal was triggered last time, or the signal has not been reset");
61 m_SignaledValue = SignalValue;
60 VERIFY(m_SignaledValue.load() == 0 && m_NumThreadsAwaken.load() == 0, "Not all threads have been awaken since the signal was triggered last time, or the signal has not been reset");
61 m_SignaledValue.store(SignalValue);
6262 }
6363 // Unlocking is done before notifying, to avoid waking up the waiting
6464 // thread only to block again (see notify_one for details)
8686 std::unique_lock<std::mutex> Lock(m_Mutex);
8787 // It is safe to check m_SignaledValue since we are holding
8888 // the mutex
89 if (m_SignaledValue == 0)
89 if (m_SignaledValue.load() == 0)
9090 {
91 m_CondVar.wait(Lock, [&] { return m_SignaledValue != 0; });
91 m_CondVar.wait(Lock, [&] { return m_SignaledValue.load() != 0; });
9292 }
93 int SignaledValue = m_SignaledValue;
94 // Count the number of threads awaken while holding the mutex
95 ++m_NumThreadsAwaken;
93 auto SignaledValue = m_SignaledValue.load();
94 // Update the number of threads awaken while holding the mutex
95 const auto NumThreadsAwaken = m_NumThreadsAwaken.fetch_add(1) + 1;
96 // fetch_add returns the original value immediately preceding the addition.
9697 if (AutoReset)
9798 {
9899 VERIFY(NumThreadsWaiting > 0, "Number of waiting threads must not be 0 when auto resetting the signal");
99100 // Reset the signal while holding the mutex. If Trigger() is executed by another
100101 // thread, it will wait until we release the mutex
101 if (m_NumThreadsAwaken == NumThreadsWaiting)
102 if (NumThreadsAwaken == NumThreadsWaiting)
102103 {
103 m_SignaledValue = 0;
104 m_NumThreadsAwaken = 0;
104 m_SignaledValue.store(0);
105 m_NumThreadsAwaken.store(0);
105106 }
106107 }
107108 return SignaledValue;
110111 void Reset()
111112 {
112113 std::lock_guard<std::mutex> Lock{m_Mutex};
113 m_SignaledValue = 0;
114 m_NumThreadsAwaken = 0;
114 m_SignaledValue.store(0);
115 m_NumThreadsAwaken.store(0);
115116 }
116117
117 bool IsTriggered() const { return m_SignaledValue != 0; }
118 bool IsTriggered() const { return m_SignaledValue.load() != 0; }
118119
119120 private:
120121 std::mutex m_Mutex;
121122 std::condition_variable m_CondVar;
122 std::atomic_int m_SignaledValue;
123 std::atomic_int m_NumThreadsAwaken;
123 std::atomic_int m_SignaledValue{0};
124 std::atomic_int m_NumThreadsAwaken{0};
124125
125126 Signal(const Signal&) = delete;
126127 Signal& operator=(const Signal&) = delete;