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/lazy-instance.h"
9#if V8_OS_WIN
10#include "src/base/win32-headers.h"
11#endif
12
13#if V8_OS_MACOSX
14#include <mach/semaphore.h>  // NOLINT
15#elif V8_OS_POSIX
16#include <semaphore.h>  // NOLINT
17#endif
18
19namespace v8 {
20namespace base {
21
22// Forward declarations.
23class TimeDelta;
24
25// ----------------------------------------------------------------------------
26// Semaphore
27//
28// A semaphore object is a synchronization object that maintains a count. The
29// count is decremented each time a thread completes a wait for the semaphore
30// object and incremented each time a thread signals the semaphore. When the
31// count reaches zero,  threads waiting for the semaphore blocks until the
32// count becomes non-zero.
33
34class Semaphore FINAL {
35 public:
36  explicit Semaphore(int count);
37  ~Semaphore();
38
39  // Increments the semaphore counter.
40  void Signal();
41
42  // Suspends the calling thread until the semaphore counter is non zero
43  // and then decrements the semaphore counter.
44  void Wait();
45
46  // Suspends the calling thread until the counter is non zero or the timeout
47  // time has passed. If timeout happens the return value is false and the
48  // counter is unchanged. Otherwise the semaphore counter is decremented and
49  // 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 v8::base
100
101#endif  // V8_BASE_PLATFORM_SEMAPHORE_H_
102