@@ -24,6 +24,33 @@ namespace modm
24
24
// / @ingroup modm_processing_resumable
25
25
// / @{
26
26
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
+
27
54
// / Resumable functions implemented via fibers return like a normal function
28
55
template < typename T >
29
56
using ResumableResult = T;
@@ -33,80 +60,80 @@ template< uint8_t Functions = 1 >
33
60
class Resumable
34
61
{
35
62
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);
63
90
64
91
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
81
108
};
82
109
83
110
// / Resumable functions implemented via fibers are normal functions
84
111
template < uint8_t Levels = 1 >
85
112
class NestedResumable
86
113
{
87
114
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 ();
98
125
99
126
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
+ }
107
134
108
- modm::fiber::recursive_mutex rfState;
109
- // / @endcond
135
+ ResumableRecursiveMutex rfState;
136
+ // / @endcond
110
137
};
111
138
112
139
// / @}
0 commit comments