Mercury Currency Engine
mutex.hpp
Go to the documentation of this file.
1 //SPDX-License-Identifier: Apache-2.0
2 //Author: Blayne Dennis
7 #ifndef __MERCURY_COROUTINE_ENGINE_MUTEX__
8 #define __MERCURY_COROUTINE_ENGINE_MUTEX__
9 
10 // c++
11 #include <mutex>
12 
13 // locals
14 #include "atomic.hpp"
15 #include "scheduler.hpp"
16 
17 namespace mce {
18 
19 // Mutex class safe to use in both coroutines and normal code.
20 struct mutex
21 {
22  mutex() : acquired_{false} { }
23  mutex(const mce::mutex&) = delete;
24 
26  inline void lock()
27  {
28  std::unique_lock<mce::spinlock> lk(lk_);
29  if(acquired_)
30  {
31  do
32  {
34  notify_q_.push_back(&p);
35  p.park(lk);
36  } while(acquired_);
37  acquired_ = true;
38  }
39  else { acquired_ = true; }
40  }
41 
43  inline void unlock()
44  {
45  std::unique_lock<mce::spinlock> lk(lk_);
46  if(acquired_)
47  {
48  acquired_ = false;
49  if(notify_q_.size())
50  {
51  notify_q_.front()->unpark(lk);
52  notify_q_.pop_front();
53  }
54  }
55  else{ throw mutex_already_unlocked_exception(); }
56  }
57 
59  inline bool try_lock() // returns true if lock acquired, else false
60  {
61  std::unique_lock<mce::spinlock> lk(lk_);
62  if(!acquired_)
63  {
64  acquired_ = true;
65  return true;
66  }
67  else { return false; }
68  }
69 
70  class mutex_already_unlocked_exception : public std::exception
71  {
72  virtual const char* what() const throw()
73  {
74  return "Cannot unlock an already unlocked mutex";
75  }
76  };
77 
78 private:
79  // spinlock always acquired *temporarily*. This is required to synchronize
80  // the coroutine parking process.
81  mce::spinlock lk_;
82  bool acquired_;
83  scheduler::parkable_queue notify_q_;
84 };
85 
86 }
87 
88 #endif
Definition: mutex.hpp:21
bool try_lock()
Attempt to the lock the mutex, returning true if successful, else false.
Definition: mutex.hpp:59
void unlock()
Unlock the mutex.
Definition: mutex.hpp:43
void lock()
Lock the mutex, blocking until lock is acquired.
Definition: mutex.hpp:26
object containing information to block and unblock a coroutine (running in a scheduler) or thread
Definition: scheduler.hpp:268
void park(LOCK &lk)
blocking call until unpark, unlocks and relocks given lock as necessary
Definition: scheduler.hpp:283
mce::detail::queue< parkable * > parkable_queue
most straightforward blocked queue
Definition: scheduler.hpp:428
Core mechanism for atomic synchronization.
Definition: atomic.hpp:20