1// Copyright 2013 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_BASE_PLATFORM_SEMAPHORE_H_
6#define V8_BASE_PLATFORM_SEMAPHORE_H_
7
8#include "src/base/base-export.h"
9#include "src/base/lazy-instance.h"
10#if V8_OS_WIN
11#include "src/base/win32-headers.h"
12#endif
13
14#if V8_OS_MACOSX
15#include <mach/semaphore.h>  // NOLINT
16#elif V8_OS_POSIX
17#include <semaphore.h>  // NOLINT
18#endif
19
20namespace v8 {
21namespace base {
22
23// Forward declarations.
24class TimeDelta;
25
26// ----------------------------------------------------------------------------
27// Semaphore
28//
29// A semaphore object is a synchronization object that maintains a count. The
30// count is decremented each time a thread completes a wait for the semaphore
31// object and incremented each time a thread signals the semaphore. When the
32// count reaches zero,  threads waiting for the semaphore blocks until the
33// count becomes non-zero.
34
35class V8_BASE_EXPORT Semaphore final {
36 public:
37  explicit Semaphore(int count);
38  ~Semaphore();
39
40  // Increments the semaphore counter.
41  void Signal();
42
43  // Decrements the semaphore counter if it is positive, or blocks until it
44  // becomes positive and then decrements the counter.
45  void Wait();
46
47  // Like Wait() but returns after rel_time time has passed. If the timeout
48  // happens the return value is false and the counter is unchanged. Otherwise
49  // the semaphore counter is decremented and true is returned.
50  bool WaitFor(const TimeDelta& rel_time) WARN_UNUSED_RESULT;
51
52#if V8_OS_MACOSX
53  typedef semaphore_t NativeHandle;
54#elif V8_OS_POSIX
55  typedef sem_t NativeHandle;
56#elif V8_OS_WIN
57  typedef HANDLE NativeHandle;
58#endif
59
60  NativeHandle& native_handle() {
61    return native_handle_;
62  }
63  const NativeHandle& native_handle() const {
64    return native_handle_;
65  }
66
67 private:
68  NativeHandle native_handle_;
69
70  DISALLOW_COPY_AND_ASSIGN(Semaphore);
71};
72
73
74// POD Semaphore initialized lazily (i.e. the first time Pointer() is called).
75// Usage:
76//   // The following semaphore starts at 0.
77//   static LazySemaphore<0>::type my_semaphore = LAZY_SEMAPHORE_INITIALIZER;
78//
79//   void my_function() {
80//     // Do something with my_semaphore.Pointer().
81//   }
82//
83
84template <int N>
85struct CreateSemaphoreTrait {
86  static Semaphore* Create() {
87    return new Semaphore(N);
88  }
89};
90
91template <int N>
92struct LazySemaphore {
93  typedef typename LazyDynamicInstance<Semaphore, CreateSemaphoreTrait<N>,
94                                       ThreadSafeInitOnceTrait>::type type;
95};
96
97#define LAZY_SEMAPHORE_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
98
99}  // namespace base
100}  // namespace v8
101
102#endif  // V8_BASE_PLATFORM_SEMAPHORE_H_
103