blob: c7a6fe48955fd1f478d3b770f276e07d21662c1f [file] [log] [blame]
Benoit Jacoba0ba3ac2019-04-08 12:00:37 -04001#ifndef TENSORFLOW_LITE_EXPERIMENTAL_RUY_BLOCKING_COUNTER_H_
2#define TENSORFLOW_LITE_EXPERIMENTAL_RUY_BLOCKING_COUNTER_H_
3
4#include <atomic>
5#include <cstdint>
6
7namespace ruy {
8
9// A BlockingCounter lets one thread to wait for N events to occur.
10// This is how the master thread waits for all the worker threads
11// to have finished working.
12// The waiting is done using a naive spinlock waiting for the atomic
13// count_ to hit the value 0. This is acceptable because in our usage
14// pattern, BlockingCounter is used only to synchronize threads after
15// short-lived tasks (performing parts of the same GEMM). It is not used
16// for synchronizing longer waits (resuming work on the next GEMM).
17class BlockingCounter {
18 public:
19 BlockingCounter() : count_(0) {}
20
21 // Sets/resets the counter; initial_count is the number of
22 // decrementing events that the Wait() call will be waiting for.
23 void Reset(std::size_t initial_count);
24
25 // Decrements the counter; if the counter hits zero, signals
26 // the threads that were waiting for that, and returns true.
27 // Otherwise (if the decremented count is still nonzero),
28 // returns false.
29 bool DecrementCount();
30
31 // Waits for the N other threads (N having been set by Reset())
32 // to hit the BlockingCounter.
33 void Wait();
34
35 private:
36 std::atomic<std::size_t> count_;
37};
38
39} // namespace ruy
40
41#endif // TENSORFLOW_LITE_EXPERIMENTAL_RUY_BLOCKING_COUNTER_H_