Skip to content

Commit 2658292

Browse files
committed
[resumable] Remove unnecessary dependency on atomic fiber mutex
1 parent e583a8c commit 2658292

File tree

3 files changed

+92
-79
lines changed

3 files changed

+92
-79
lines changed

src/modm/processing/fiber/mutex.hpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,6 @@
2222
#include <atomic>
2323
#include <mutex>
2424

25-
/// @cond
26-
namespace modm
27-
{
28-
template< uint8_t Functions > class Resumable;
29-
template< uint8_t Levels > class NestedResumable;
30-
}
31-
/// @endcond
32-
3325
namespace modm::fiber
3426
{
3527

@@ -40,9 +32,6 @@ namespace modm::fiber
4032
/// @see https://en.cppreference.com/w/cpp/thread/mutex
4133
class mutex
4234
{
43-
template< uint8_t Functions > friend class ::modm::Resumable;
44-
template< uint8_t Levels > friend class ::modm::NestedResumable;
45-
4635
mutex(const mutex&) = delete;
4736
mutex& operator=(const mutex&) = delete;
4837

@@ -98,9 +87,6 @@ class timed_mutex : public mutex
9887
/// @see https://en.cppreference.com/w/cpp/thread/recursive_mutex
9988
class recursive_mutex
10089
{
101-
template< uint8_t Functions > friend class ::modm::Resumable;
102-
template< uint8_t Levels > friend class ::modm::NestedResumable;
103-
10490
recursive_mutex(const recursive_mutex&) = delete;
10591
recursive_mutex& operator=(const recursive_mutex&) = delete;
10692
using count_t = uint16_t;

src/modm/processing/resumable/macros_fiber.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#define MODM_RF_MACROS_FIBER_HPP
1414

1515
#include <modm/processing/fiber.hpp>
16-
#include <modm/processing/fiber/mutex.hpp>
16+
#include <mutex>
1717

1818
/// @ingroup modm_processing_resumable
1919
/// @{
@@ -109,12 +109,12 @@
109109

110110
#define RF_BEGIN_0() \
111111
this->template checkRfType<true>(); \
112-
modm::fiber::lock_guard rfLockGuardState{this->rfState};
112+
::std::lock_guard rfLockGuardState{this->rfState};
113113

114114
#define RF_BEGIN_1(index) \
115115
this->template checkRfType<false>(); \
116116
this->template checkRfFunctions<index>(); \
117-
modm::fiber::lock_guard rfLockGuardState{this->rfStateArray[index]};
117+
::std::lock_guard rfLockGuardState{this->rfStateArray[index]};
118118

119119
#define MODM_RF_GET_MACRO(_0, _1, NAME, ...) NAME
120120
#define RF_BEGIN(...) MODM_RF_GET_MACRO(_0 __VA_OPT__(,) __VA_ARGS__, RF_BEGIN_1, RF_BEGIN_0)(__VA_ARGS__)

src/modm/processing/resumable/resumable_fiber.hpp

Lines changed: 89 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,33 @@ namespace modm
2424
/// @ingroup modm_processing_resumable
2525
/// @{
2626

27+
/// @cond
28+
// Reimplementations of modm::fiber::(recursive_)mutex without atomics
29+
struct ResumableMutex
30+
{
31+
bool locked{false};
32+
void inline lock() { while(locked) modm::this_fiber::yield(); locked = true; }
33+
void inline unlock() { locked = false; }
34+
};
35+
struct ResumableRecursiveMutex
36+
{
37+
using count_t = uint16_t;
38+
static constexpr fiber::id NoOwner{fiber::id(-1)};
39+
fiber::id owner{NoOwner};
40+
static constexpr count_t countMax{count_t(-1)};
41+
count_t count{1};
42+
bool inline try_lock()
43+
{
44+
const auto id = modm::this_fiber::get_id();
45+
if (owner == NoOwner) { owner = id; return true; }
46+
if (owner == id and count < countMax) { count++; return true; }
47+
return false;
48+
}
49+
void inline lock() { while(not try_lock()) modm::this_fiber::yield(); }
50+
void inline unlock() { if (count > 1) count--; else owner = NoOwner; }
51+
};
52+
/// @endcond
53+
2754
/// Resumable functions implemented via fibers return like a normal function
2855
template < typename T >
2956
using ResumableResult = T;
@@ -33,80 +60,80 @@ template< uint8_t Functions = 1 >
3360
class Resumable
3461
{
3562
public:
36-
bool isResumableRunning(uint8_t id) const
37-
{
38-
return id < Functions and rfStateArray[id].locked;
39-
}
40-
bool areAnyResumablesRunning() const
41-
{
42-
for (const auto &state : rfStateArray) if (state.locked) return true;
43-
return false;
44-
}
45-
bool areAnyResumablesRunning(std::initializer_list<uint8_t> ids) const
46-
{
47-
for (uint8_t id : ids) if (isResumableRunning(id)) return true;
48-
return false;
49-
}
50-
bool areAllResumablesRunning(std::initializer_list<uint8_t> ids) const
51-
{
52-
for (uint8_t id : ids) if (not isResumableRunning(id)) return false;
53-
return true;
54-
}
55-
bool joinResumables(std::initializer_list<uint8_t> ids) const
56-
{
57-
modm::this_fiber::poll([&]{ return not areAnyResumablesRunning(ids); });
58-
return true;
59-
}
60-
// unimplementable with fibers, but may be stubbed by user application
61-
void stopAllResumables();
62-
bool stopResumable(uint8_t id);
63+
bool isResumableRunning(uint8_t id) const
64+
{
65+
return id < Functions and rfStateArray[id].locked;
66+
}
67+
bool areAnyResumablesRunning() const
68+
{
69+
for (const auto &state : rfStateArray) if (state.locked) return true;
70+
return false;
71+
}
72+
bool areAnyResumablesRunning(std::initializer_list<uint8_t> ids) const
73+
{
74+
for (uint8_t id : ids) if (isResumableRunning(id)) return true;
75+
return false;
76+
}
77+
bool areAllResumablesRunning(std::initializer_list<uint8_t> ids) const
78+
{
79+
for (uint8_t id : ids) if (not isResumableRunning(id)) return false;
80+
return true;
81+
}
82+
bool joinResumables(std::initializer_list<uint8_t> ids) const
83+
{
84+
modm::this_fiber::poll([&]{ return not areAnyResumablesRunning(ids); });
85+
return true;
86+
}
87+
// unimplementable with fibers, but may be stubbed by user application
88+
void stopAllResumables();
89+
bool stopResumable(uint8_t id);
6390

6491
protected:
65-
/// @cond
66-
template<uint8_t index>
67-
static void
68-
checkRfFunctions()
69-
{
70-
static_assert(index < Functions,
71-
"Index out of bounds! Increase the `Functions` template argument of your Resumable class.");
72-
}
73-
template<bool isNested>
74-
static void
75-
checkRfType()
76-
{
77-
static_assert(isNested == false, "You must declare an index for this resumable function!");
78-
}
79-
modm::fiber::mutex rfStateArray[Functions];
80-
/// @endcond
92+
/// @cond
93+
template<uint8_t index>
94+
static void
95+
checkRfFunctions()
96+
{
97+
static_assert(index < Functions,
98+
"Index out of bounds! Increase the `Functions` template argument of your Resumable class.");
99+
}
100+
template<bool isNested>
101+
static void
102+
checkRfType()
103+
{
104+
static_assert(isNested == false, "You must declare an index for this resumable function!");
105+
}
106+
ResumableMutex rfStateArray[Functions];
107+
/// @endcond
81108
};
82109

83110
/// Resumable functions implemented via fibers are normal functions
84111
template< uint8_t Levels = 1 >
85112
class NestedResumable
86113
{
87114
public:
88-
bool isResumableRunning() const
89-
{
90-
return rfState.owner != rfState.NoOwner;
91-
}
92-
int8_t getResumableDepth() const
93-
{
94-
return isResumableRunning() ? rfState.count - 1 : -1;
95-
}
96-
// unimplementable with fibers, but may be stubbed by user application
97-
void stopResumable();
115+
bool isResumableRunning() const
116+
{
117+
return rfState.owner != rfState.NoOwner;
118+
}
119+
int8_t getResumableDepth() const
120+
{
121+
return isResumableRunning() ? rfState.count - 1 : -1;
122+
}
123+
// unimplementable with fibers, but may be stubbed by user application
124+
void stopResumable();
98125

99126
protected:
100-
/// @cond
101-
template<bool isNested>
102-
static void
103-
checkRfType()
104-
{
105-
static_assert(isNested == true, "You cannot declare an index for a _nested_ resumable function!");
106-
}
127+
/// @cond
128+
template<bool isNested>
129+
static void
130+
checkRfType()
131+
{
132+
static_assert(isNested == true, "You cannot declare an index for a _nested_ resumable function!");
133+
}
107134

108-
modm::fiber::recursive_mutex rfState;
109-
/// @endcond
135+
ResumableRecursiveMutex rfState;
136+
/// @endcond
110137
};
111138

112139
/// @}

0 commit comments

Comments
 (0)