Pioneer
Loading...
Searching...
No Matches
Semaphore.h
Go to the documentation of this file.
1//---------------------------------------------------------
2// Heavily adapted version of:
3// sema.h - C++11 On Multicore
4// Copyright (c) 2015 Jeff Preshing
5// Released under the zlib License
6// For conditions of distribution and use, see
7// https://github.com/preshing/cpp11-on-multicore/blob/master/LICENSE
8//---------------------------------------------------------
9
10#pragma once
11
12#include "SDL_mutex.h"
13#include <atomic_queue/defs.h>
14
15// Lightweight spinlock semaphore
16class Semaphore {
17public:
18 Semaphore(uint32_t initialCount = 0) :
19 m_sem(SDL_CreateSemaphore(0)),
20 m_count(initialCount)
21 {}
22
24 {
25 SDL_DestroySemaphore(m_sem);
26 }
27
28 // return the number of waiting threads
29 int32_t count() const { return -m_count.load(std::memory_order_acquire); }
30
31 bool try_wait()
32 {
33 int value = m_count.load(std::memory_order_relaxed);
34 return (value > 0 && m_count.compare_exchange_strong(value, value - 1, std::memory_order_acquire));
35 }
36
37 void wait()
38 {
39 if (!try_wait())
40 wait_with_spinlock();
41 }
42
43 // immediately wait without spinning if the semaphore is not signalled
44 void waitonly()
45 {
46 if (!try_wait()) {
47 int value = m_count.fetch_sub(1, std::memory_order_acquire);
48 if (value <= 0)
49 SDL_SemWait(m_sem);
50 }
51 }
52
53 void signal(int count = 1)
54 {
55 int value = m_count.fetch_add(count, std::memory_order_release);
56 int toRelease = -value < count ? -value : count;
57 while (toRelease-- > 0) {
58 SDL_SemPost(m_sem);
59 }
60 }
61
62private:
63 void wait_with_spinlock()
64 {
65 uint32_t spinCount = 1000;
66 int32_t value = 0;
67
68 while (spinCount--) {
69 value = m_count.load(std::memory_order_relaxed);
70 if ((value > 0) && m_count.compare_exchange_strong(value, value - 1, std::memory_order_acquire))
71 return;
72 atomic_queue::spin_loop_pause();
73 // keep the compiler from detrimentally optimizing the loop
74 std::atomic_signal_fence(std::memory_order_acquire);
75 }
76
77 value = m_count.fetch_sub(1, std::memory_order_acquire);
78 if (value <= 0)
79 SDL_SemWait(m_sem);
80 }
81
82 SDL_semaphore *m_sem;
83 std::atomic<int32_t> m_count;
84};
Definition Semaphore.h:16
void signal(int count=1)
Definition Semaphore.h:53
int32_t count() const
Definition Semaphore.h:29
void waitonly()
Definition Semaphore.h:44
Semaphore(uint32_t initialCount=0)
Definition Semaphore.h:18
~Semaphore()
Definition Semaphore.h:23
void wait()
Definition Semaphore.h:37
bool try_wait()
Definition Semaphore.h:31