tenno 0.1.0
Loading...
Searching...
No Matches
mutex.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: MIT
2// Author: Giovanni Santini
3// Mail: giovanni.santini@proton.me
4// Github: @San7o
5
6#pragma once
7
8namespace tenno
9{
10
14class mutex
15{
16public:
17 mutex() = default;
18 ~mutex() = default;
19
23 inline void lock() noexcept
24 {
25 int expected = 0;
26
27#if defined(__GNUC__) || !defined(__clang__)
28 while (!__atomic_compare_exchange_n(
29 &this->is_locked, /* Address of the mutex variable */
30 &expected, /* address of the expected value */
31 1, /* desired value */
32 0, /* strong compare-and-swap (retry on failure) */
33 __ATOMIC_SEQ_CST, /* memory order */
34 __ATOMIC_SEQ_CST))
35 {
36 expected = 0;
37 }
38#elif __x86_64__
39 while (true)
40 {
41 asm volatile("movl %1, %%eax\n\t" /* move expexted value to eax */
42 "lock cmpxchgl %2, %0\n\t" /* compare and exchange */
43 : "+m"(this->is_locked) /* %0: output operand */
44 : "r"(expected), /* %1: expected value (input) */
45 "r"(1) /* %2: new value to set */
46 : "eax", "memory" /* clobbered registers */
47 );
48
49 if (this->is_locked == 1)
50 {
51 return;
52 }
53
54 asm volatile("pause");
55 }
56#else
57#error "Unsupported platform"
58#endif
59 }
60
66 inline bool try_lock() noexcept
67 {
68 int expected = 0;
69
70#if defined(__GNUC__) || !defined(__clang__)
71 return __atomic_compare_exchange_n(
72 &this->is_locked, /* Address of the mutex variable */
73 &expected, /* address of the expected value */
74 1, /* desired value */
75 0, /* strong compare-and-swap (retry on failure) */
76 __ATOMIC_SEQ_CST, /* memory order */
77 __ATOMIC_SEQ_CST);
78#elif __x86_64__
79 asm volatile("movl %1, %%eax\n\t" /* move expexted value to eax */
80 "lock cmpxchgl %2, %0\n\t" /* compare and exchange */
81 : "+m"(this->is_locked) /* %0: output operand */
82 : "r"(expected), /* %1: expected value (input) */
83 "r"(1) /* %2: new value to set */
84 : "eax", "memory" /* clobbered registers */
85 );
86
87 return (bool) this->is_locked;
88
89#else
90#error "Unsupported platform"
91#endif
92 }
93
97 inline void unlock() noexcept
98 {
99#if defined(__GNUC__) || !defined(__clang__)
100 __atomic_store_n(&this->is_locked, 0, __ATOMIC_SEQ_CST);
101#elif __x86_64__
102 asm volatile("movl $0, %0\n\t" /* set the state to 0 */
103 : "+m"(this->is_locked) /* %0: output operand */
104 : /* no input operands */
105 : "memory" /* clobbered registers */
106 );
107#else
108#error "Unsupported platform"
109#endif
110 }
111
112#ifndef TENNO_DEBUG
113private:
114#endif
115 volatile int is_locked = 0;
116};
117
125template <typename M> class lock_guard
126{
127public:
128 explicit lock_guard(M &m) : _m(m)
129 {
130 this->_m.lock();
131 }
132
134 {
135 this->_m.unlock();
136 }
137
138 void operator=(const lock_guard &) = delete;
139
140private:
141 M &_m;
142};
143
144} // namespace tenno
An expected value.
Definition expected.hpp:38
A simple lock guard implementation.
Definition mutex.hpp:126
void operator=(const lock_guard &)=delete
A simple mutex implementation.
Definition mutex.hpp:15
~mutex()=default
void lock() noexcept
Lock the mutex.
Definition mutex.hpp:23
mutex()=default
void unlock() noexcept
Unlock the mutex.
Definition mutex.hpp:97
bool try_lock() noexcept
Try to lock the mutex.
Definition mutex.hpp:66