29
29
SerialDispatcher::SerialDispatcher (arduino::HardwareSerial & serial)
30
30
: _is_initialized{false }
31
31
, _mutex{}
32
- , _cond{_mutex}
33
32
, _serial{serial}
34
33
, _thread(osPriorityRealtime, 4096 , nullptr , " SerialDispatcher" )
35
34
, _has_tread_started{false }
@@ -68,11 +67,8 @@ void SerialDispatcher::begin(unsigned long baudrate, uint16_t config)
68
67
/* Since the thread is not in the list yet we are
69
68
* going to create a new entry to the list.
70
69
*/
71
- ThreadCustomerData data;
72
- data.thread_id = current_thread_id;
73
- data.block_tx_buffer = false ;
74
- data.prefix_func = nullptr ;
75
- data.suffix_func = nullptr ;
70
+ uint32_t const thread_event_flag = (1 <<(_thread_customer_list.size ()));
71
+ ThreadCustomerData data{current_thread_id, thread_event_flag};
76
72
_thread_customer_list.push_back (data);
77
73
}
78
74
}
@@ -87,7 +83,10 @@ void SerialDispatcher::end()
87
83
osThreadId_t const current_thread_id = rtos::ThisThread::get_id ();
88
84
std::remove_if (std::begin (_thread_customer_list),
89
85
std::end (_thread_customer_list),
90
- [current_thread_id](ThreadCustomerData const d) -> bool { return (d.thread_id == current_thread_id); });
86
+ [current_thread_id](ThreadCustomerData const d) -> bool
87
+ {
88
+ return (d.thread_id == current_thread_id);
89
+ });
91
90
92
91
/* If no thread consumers are left also end
93
92
* the serial device altogether.
@@ -104,7 +103,7 @@ int SerialDispatcher::available()
104
103
{
105
104
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
106
105
auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
107
- if (iter == std::end (_thread_customer_list)) return 0 ;
106
+ assert (iter != std::end (_thread_customer_list));
108
107
109
108
prepareSerialReader (iter);
110
109
handleSerialReader ();
@@ -116,7 +115,7 @@ int SerialDispatcher::peek()
116
115
{
117
116
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
118
117
auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
119
- if (iter == std::end (_thread_customer_list)) return 0 ;
118
+ assert (iter != std::end (_thread_customer_list));
120
119
121
120
prepareSerialReader (iter);
122
121
handleSerialReader ();
@@ -128,7 +127,7 @@ int SerialDispatcher::read()
128
127
{
129
128
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
130
129
auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
131
- if (iter == std::end (_thread_customer_list)) return 0 ;
130
+ assert (iter != std::end (_thread_customer_list));
132
131
133
132
prepareSerialReader (iter);
134
133
handleSerialReader ();
@@ -150,14 +149,8 @@ size_t SerialDispatcher::write(uint8_t const b)
150
149
size_t SerialDispatcher::write (const uint8_t * data, size_t len)
151
150
{
152
151
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
153
-
154
152
auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
155
-
156
- /* If this thread hasn't registered yet
157
- * with the SerialDispatcher via 'begin'.
158
- */
159
- if (iter == std::end (_thread_customer_list))
160
- return 0 ;
153
+ assert (iter != std::end (_thread_customer_list));
161
154
162
155
size_t bytes_written = 0 ;
163
156
for (; (bytes_written < len) && iter->tx_buffer .availableForStore (); bytes_written++)
@@ -166,7 +159,7 @@ size_t SerialDispatcher::write(const uint8_t * data, size_t len)
166
159
/* Inform the worker thread that new data has
167
160
* been written to a Serial transmit buffer.
168
161
*/
169
- _cond. notify_one ( );
162
+ _data_available_for_transmit. set (iter-> thread_event_flag );
170
163
171
164
return bytes_written;
172
165
}
@@ -175,32 +168,37 @@ void SerialDispatcher::block()
175
168
{
176
169
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
177
170
auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
178
- if (iter == std::end (_thread_customer_list)) return ;
171
+ assert (iter != std::end (_thread_customer_list));
172
+
179
173
iter->block_tx_buffer = true ;
180
174
}
181
175
182
176
void SerialDispatcher::unblock ()
183
177
{
184
178
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
185
179
auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
186
- if (iter == std::end (_thread_customer_list)) return ;
180
+ assert (iter != std::end (_thread_customer_list));
181
+
187
182
iter->block_tx_buffer = false ;
188
- _cond.notify_one ();
183
+
184
+ _data_available_for_transmit.set (iter->thread_event_flag );
189
185
}
190
186
191
187
void SerialDispatcher::prefix (PrefixInjectorCallbackFunc func)
192
188
{
193
189
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
194
190
auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
195
- if (iter == std::end (_thread_customer_list)) return ;
191
+ assert (iter != std::end (_thread_customer_list));
192
+
196
193
iter->prefix_func = func;
197
194
}
198
195
199
196
void SerialDispatcher::suffix (SuffixInjectorCallbackFunc func)
200
197
{
201
198
mbed::ScopedLock<rtos::Mutex> lock (_mutex);
202
199
auto iter = findThreadCustomerDataById (rtos::ThisThread::get_id ());
203
- if (iter == std::end (_thread_customer_list)) return ;
200
+ assert (iter != std::end (_thread_customer_list));
201
+
204
202
iter->suffix_func = func;
205
203
}
206
204
@@ -226,12 +224,10 @@ void SerialDispatcher::threadFunc()
226
224
227
225
while (!_terminate_thread)
228
226
{
229
- /* Prevent race conditions by multi-threaded
230
- * access to shared data.
231
- */
232
- mbed::ScopedLock<rtos::Mutex> lock (_mutex);
233
- /* Wait for new data to be available */
234
- _cond.wait ();
227
+ /* Wait for data to be available in a transmit buffer. */
228
+ static uint32_t constexpr ALL_EVENT_FLAGS = 0x7fffffff ;
229
+ _data_available_for_transmit.wait_any (ALL_EVENT_FLAGS, osWaitForever, /* clear */ true );
230
+
235
231
/* Iterate over all list entries. */
236
232
std::for_each (std::begin (_thread_customer_list),
237
233
std::end (_thread_customer_list),
@@ -303,7 +299,10 @@ std::list<SerialDispatcher::ThreadCustomerData>::iterator SerialDispatcher::find
303
299
{
304
300
return std::find_if (std::begin (_thread_customer_list),
305
301
std::end (_thread_customer_list),
306
- [thread_id](ThreadCustomerData const d) -> bool { return (d.thread_id == thread_id); });
302
+ [thread_id](ThreadCustomerData const d) -> bool
303
+ {
304
+ return (d.thread_id == thread_id);
305
+ });
307
306
}
308
307
309
308
void SerialDispatcher::prepareSerialReader (std::list<ThreadCustomerData>::iterator & iter)
0 commit comments