1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_HEAP_BARRIER_H_
6 #define V8_HEAP_BARRIER_H_
7 
8 #include "src/base/platform/condition-variable.h"
9 #include "src/base/platform/mutex.h"
10 
11 namespace v8 {
12 namespace internal {
13 
14 // Barrier that can be used once to synchronize a dynamic number of tasks
15 // working concurrently.
16 //
17 // Usage:
18 //   void RunConcurrently(OneShotBarrier* shared_barrier) {
19 //     shared_barrier->Start();
20 //     do {
21 //       {
22 //         /* process work and create new work */
23 //         barrier->NotifyAll();
24 //         /* process work and create new work */
25 //       }
26 //     } while(!shared_barrier->Wait());
27 //   }
28 //
29 // Note: If Start() is not called in time, e.g., because the first concurrent
30 // task is already done processing all work, then Done() will return true
31 // immediately.
32 class OneshotBarrier {
33  public:
OneshotBarrier()34   OneshotBarrier() : tasks_(0), waiting_(0), done_(false) {}
35 
Start()36   void Start() {
37     base::LockGuard<base::Mutex> guard(&mutex_);
38     tasks_++;
39   }
40 
NotifyAll()41   void NotifyAll() {
42     base::LockGuard<base::Mutex> guard(&mutex_);
43     if (waiting_ > 0) condition_.NotifyAll();
44   }
45 
Wait()46   bool Wait() {
47     base::LockGuard<base::Mutex> guard(&mutex_);
48     if (done_) return true;
49 
50     DCHECK_LE(waiting_, tasks_);
51     waiting_++;
52     if (waiting_ == tasks_) {
53       done_ = true;
54       condition_.NotifyAll();
55     } else {
56       // Spurious wakeup is ok here.
57       condition_.Wait(&mutex_);
58     }
59     waiting_--;
60     return done_;
61   }
62 
63   // Only valid to be called in a sequential setting.
DoneForTesting()64   bool DoneForTesting() const { return done_; }
65 
66  private:
67   base::ConditionVariable condition_;
68   base::Mutex mutex_;
69   int tasks_;
70   int waiting_;
71   bool done_;
72 };
73 
74 }  // namespace internal
75 }  // namespace v8
76 
77 #endif  // V8_HEAP_BARRIER_H_
78