FreeRTOScpp
MutexCPP.h
Go to the documentation of this file.
1 /**
2  * @file MutexCPP.h
3  * @brief FreeRTOS Mutex Wrapper
4  *
5  * This file contains a set of lightweight wrappers for mutexes using FreeRTOS
6  *
7  * @copyright (c) 2007-2024 Richard Damon
8  * @author Richard Damon <richard.damon@gmail.com>
9  * @parblock
10  * MIT License:
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a copy
13  * of this software and associated documentation files (the "Software"), to deal
14  * in the Software without restriction, including without limitation the rights
15  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16  * copies of the Software, and to permit persons to whom the Software is
17  * furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included in
20  * all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28  * THE SOFTWARE.
29  *
30  * It is requested (but not required by license) that any bugs found or
31  * improvements made be shared, preferably to the author.
32  * @endparblock
33  *
34  * @ingroup FreeRTOSCpp
35  */
36 
37 #ifndef MUTEXCPP_H
38 #define MUTEXCPP_H
39 
40 #include "FreeRTOScpp.h"
41 
42 #include "Lock.h"
43 #include "semphr.h"
44 
45 #if FREERTOSCPP_USE_NAMESPACE
46 namespace FreeRTOScpp {
47 #endif
48 
49 /**
50  * @brief Mutex Wrapper.
51  *
52  * A Mutex is a basic synchronization primitive allowing mutual exclusion to be
53  * handled which also implements priority inheritance. Note, the basic mutex is
54  * NOT recursive, ie if a Task has taken the Mutex, it must not try to take it
55  * again before giving it. If you need this, use a RecurviseMutex.
56  *
57  * The usage of a Mutex is similar to a semaphore, but the task that takes the
58  * Mutex is also supposed to be the Task that eventually gives it back. It also
59  * doesn't normally make sense for an ISR to use a Mutex, so no _ISR routines
60  * have been made available.
61  *
62  * Example Usage:
63  * @code
64  * RecursiveMutex mutex("MyMutex");
65  *
66  * // In some other task
67  * mutex.take();
68  * ... // some code that needs mutual exclusion
69  * mutex.give();
70  * @endcode
71  *
72  * @ingroup FreeRTOSCpp
73  */
74 
75 class Mutex : public Lockable {
76 public:
77  /**
78  * @brief Constructor.
79  * @param name Name to give mutex, used for Debug Registry if setup
80  */
81  Mutex(char const* name) {
82 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
83  mutexHandle = xSemaphoreCreateMutexStatic(&mutexBuffer);
84 #else
85  mutexHandle = xSemaphoreCreateMutex();
86 #endif
87 #if configQUEUE_REGISTRY_SIZE > 0
88  vQueueAddToRegistry(mutexHandle, name);
89 #endif
90  }
91  /**
92  * @brief Destructor.
93  *
94  * Deletes the semaphore.
95  */
96  ~Mutex() {
97  vSemaphoreDelete(mutexHandle);
98  }
99 
100  bool take(TickType_t wait = portMAX_DELAY) override {
101  return xSemaphoreTake(mutexHandle, wait);
102  }
103 #if FREERTOSCPP_USE_CHRONO
104  bool take(Time_ms wait) {
105  return xSemaphoreTake(mutexHandle, ms2ticks(wait));
106  }
107 #endif
108 
109  bool give() override {
110  return xSemaphoreGive(mutexHandle);
111  }
112 private:
113  SemaphoreHandle_t mutexHandle;
114 #if __cplusplus < 201101L
115  Mutex(Mutex const&); ///< We are not copyable.
116  void operator =(Mutex const&); ///< We are not assignable.
117 #else
118  Mutex(Mutex const&) = delete; ///< We are not copyable.
119  void operator =(Mutex const&) = delete; ///< We are not assignable.
120 #endif // __cplusplus
121 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
122  StaticSemaphore_t mutexBuffer;
123 #endif
124 
125 };
126 
127 #if configUSE_RECURSIVE_MUTEXES > 0
128 /**
129  * @brief Recursive Mutex Wrapper.
130  *
131  * A RecursiveMutex adds the ability to nest takes, so that if you have taken the
132  * RecursiveMutex and take it again, this works and requires you to give the
133  * RecursiveMutex back as many times as it was taken before it is released.
134  *
135  * One very common application for this is for messages to the user on a console.
136  * Generally, you don't want pieces of a message interrupted by pieces of other
137  * messages, so message output routines use a mutex on the console port.
138  * These routines often use lower level routines that also want to make sure their
139  * output isn't interspersed, so each level takes the RecursiveMutex at their start
140  * and releases it at the end. Being a RecursiveMutex this works.
141  *
142  * Example Usage:
143  * @code
144  * RecursiveMutex mutex("MyMutex");
145  *
146  * // In some other task
147  * mutex.take();
148  * ...
149  * // possible in a recursive call or call to lower level routine.
150  * mutex.take();
151  * ...
152  * mutex.give();
153  * ...
154  * mutex.give();
155  *
156  * @endcode
157  * @ingroup FreeRTOSCpp
158  */
159 
160 class RecursiveMutex : public Lockable{
161 public:
162  RecursiveMutex(char const* name = nullptr) {
163 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
164  mutexHandle = xSemaphoreCreateRecursiveMutexStatic(&mutexBuffer);
165 #else
166  mutexHandle = xSemaphoreCreateRecursiveMutex();
167 #endif
168 #if configQUEUE_REGISTRY_SIZE > 0
169  if(name)
170  vQueueAddToRegistry(mutexHandle, name);
171 #endif
172  }
174  vSemaphoreDelete(mutexHandle);
175  }
176 
177  bool take(TickType_t wait = portMAX_DELAY) override {
178  return xSemaphoreTakeRecursive(mutexHandle, wait);
179  }
180  bool give() override {
181  return xSemaphoreGiveRecursive(mutexHandle);
182  }
183 
184 private:
185  SemaphoreHandle_t mutexHandle;
186 #if __cplusplus < 201101L
187  RecursiveMutex(RecursiveMutex const&); ///< We are not copyable.
188  void operator =(RecursiveMutex const&); ///< We are not assignable.
189 #else
190  RecursiveMutex(RecursiveMutex const&) = delete; ///< We are not copyable.
191  void operator =(RecursiveMutex const&) = delete; ///< We are not assignable.
192 #endif // __cplusplus
193 #if( configSUPPORT_STATIC_ALLOCATION == 1 )
194  StaticSemaphore_t mutexBuffer;
195 #endif
196 };
197 #endif // configUSE_RECURSIVE_MUTEXES
198 
199 #if FREERTOSCPP_USE_NAMESPACE
200 } // namespace FreeRTOScpp
201 #endif
202 
203 #endif // MUTEXCPP_H
bool take(TickType_t wait=portMAX_DELAY) override
Definition: MutexCPP.h:177
~Mutex()
Destructor.
Definition: MutexCPP.h:96
FreeRTOS Lock wrapper.
bool take(Time_ms wait)
Definition: MutexCPP.h:104
constexpr TickType_t ms2ticks(Time_ms ms)
Definition: FreeRTOScpp.h:81
std::chrono::milliseconds Time_ms
Definition: FreeRTOScpp.h:79
Definition: CallBack.h:63
SemaphoreHandle_t mutexHandle
Definition: MutexCPP.h:185
FreeRTOS Wrapper.
bool give() override
Definition: MutexCPP.h:180
Mutex Wrapper.
Definition: MutexCPP.h:75
A Base class to provide block based locking capability.
Definition: Lock.h:58
Recursive Mutex Wrapper.
Definition: MutexCPP.h:160
RecursiveMutex(char const *name=nullptr)
Definition: MutexCPP.h:162
Mutex(char const *name)
Constructor.
Definition: MutexCPP.h:81
~RecursiveMutex()
Definition: MutexCPP.h:173
bool take(TickType_t wait=portMAX_DELAY) override
Definition: MutexCPP.h:100
void operator=(Mutex const &)=delete
We are not assignable.
SemaphoreHandle_t mutexHandle
Definition: MutexCPP.h:113
bool give() override
Definition: MutexCPP.h:109