@@ -84,6 +84,7 @@ FileDescriptorActivity::FileDescriptorActivity(int priority, RunnableInterface*
84
84
, m_has_timeout(false )
85
85
, m_break_loop(false )
86
86
, m_trigger(false )
87
+ , m_user_timeout(false )
87
88
, m_update_sets(false )
88
89
{
89
90
FD_ZERO (&m_fd_set);
@@ -109,6 +110,7 @@ FileDescriptorActivity::FileDescriptorActivity(int scheduler, int priority, Runn
109
110
, m_has_timeout(false )
110
111
, m_break_loop(false )
111
112
, m_trigger(false )
113
+ , m_user_timeout(false )
112
114
, m_update_sets(false )
113
115
{
114
116
FD_ZERO (&m_fd_set);
@@ -125,6 +127,7 @@ FileDescriptorActivity::FileDescriptorActivity(int scheduler, int priority, Seco
125
127
, m_has_timeout(false )
126
128
, m_break_loop(false )
127
129
, m_trigger(false )
130
+ , m_user_timeout(false )
128
131
, m_update_sets(false )
129
132
{
130
133
FD_ZERO (&m_fd_set);
@@ -141,6 +144,7 @@ FileDescriptorActivity::FileDescriptorActivity(int scheduler, int priority, Seco
141
144
, m_has_timeout(false )
142
145
, m_break_loop(false )
143
146
, m_trigger(false )
147
+ , m_user_timeout(false )
144
148
, m_update_sets(false )
145
149
{
146
150
FD_ZERO (&m_fd_set);
@@ -214,8 +218,7 @@ void FileDescriptorActivity::triggerUpdateSets()
214
218
{ RTT::os::MutexLock lock (m_command_mutex);
215
219
m_update_sets = true ;
216
220
}
217
- int unused; (void )unused;
218
- unused = write (m_interrupt_pipe[1 ], &CMD_ANY_COMMAND, 1 );
221
+ writeInterruptPipe ();
219
222
}
220
223
bool FileDescriptorActivity::isUpdated (int fd) const
221
224
{ return FD_ISSET (fd, &m_fd_work); }
@@ -257,6 +260,7 @@ bool FileDescriptorActivity::start()
257
260
// reset flags
258
261
m_break_loop = false ;
259
262
m_trigger = false ;
263
+ m_user_timeout = false ;
260
264
m_update_sets = false ;
261
265
262
266
if (!Activity::start ())
@@ -271,21 +275,27 @@ bool FileDescriptorActivity::start()
271
275
}
272
276
273
277
bool FileDescriptorActivity::trigger ()
274
- {
275
- if (isActive () ) {
278
+ {
279
+ if (isActive ()) {
276
280
{ RTT::os::MutexLock lock (m_command_mutex);
277
281
m_trigger = true ;
278
282
}
279
- int unused; (void )unused;
280
- unused = write (m_interrupt_pipe[1 ], &CMD_ANY_COMMAND, 1 );
283
+ writeInterruptPipe ();
281
284
return true ;
282
285
} else
283
286
return false ;
284
287
}
285
288
286
289
bool FileDescriptorActivity::timeout ()
287
290
{
288
- return false ;
291
+ if (isActive ()) {
292
+ { RTT::os::MutexLock lock (m_command_mutex);
293
+ m_user_timeout = true ;
294
+ }
295
+ writeInterruptPipe ();
296
+ return true ;
297
+ } else
298
+ return false ;
289
299
}
290
300
291
301
@@ -294,7 +304,7 @@ struct fd_watch {
294
304
fd_watch (int & fd) : fd(fd) {}
295
305
~fd_watch ()
296
306
{
297
- if (fd != -1 )
307
+ if (fd != -1 )
298
308
close (fd);
299
309
fd = -1 ;
300
310
}
@@ -327,17 +337,18 @@ void FileDescriptorActivity::loop()
327
337
}
328
338
else
329
339
{
330
- static const int USECS_PER_SEC = 1000000 ;
340
+ static const int USECS_PER_SEC = 1000000 ;
331
341
timeval timeout = { m_timeout_us / USECS_PER_SEC,
332
- m_timeout_us % USECS_PER_SEC};
342
+ m_timeout_us % USECS_PER_SEC };
333
343
ret = select (max_fd + 1 , &m_fd_work, NULL , NULL , &timeout);
334
344
}
335
345
336
346
m_has_error = false ;
337
347
m_has_timeout = false ;
338
348
if (ret == -1 )
339
349
{
340
- log (Error) << " FileDescriptorActivity: error in select(), errno = " << errno << endlog ();
350
+ log (Error) << " FileDescriptorActivity: error in select(), errno = "
351
+ << errno << endlog ();
341
352
m_has_error = true ;
342
353
}
343
354
else if (ret == 0 )
@@ -351,33 +362,27 @@ void FileDescriptorActivity::loop()
351
362
{
352
363
// These variables are used in order to loop with select(). See the
353
364
// while() condition below.
354
- fd_set watch_pipe;
355
- timeval timeout;
356
- char dummy;
357
- do
358
- {
359
- int unused; (void )unused;
360
- unused = read (pipe , &dummy, 1 );
361
-
362
- // Initialize the values for the next select() call
363
- FD_ZERO (&watch_pipe);
364
- FD_SET (pipe , &watch_pipe);
365
- timeout.tv_sec = 0 ;
366
- timeout.tv_usec = 0 ;
367
- }
368
- while (select (pipe + 1 , &watch_pipe, NULL , NULL , &timeout) > 0 );
365
+ clearInterruptPipe ();
369
366
}
370
367
371
- // We check the flags after the command queue was emptied as we could miss commands otherwise:
368
+ // We check the flags after the command queue was emptied as we could
369
+ // miss commands otherwise:
372
370
bool do_trigger = true ;
373
371
bool user_trigger = false ;
372
+ bool user_timeout = false ;
374
373
{ RTT::os::MutexLock lock (m_command_mutex);
375
- // This section should be really fast to not block threads calling trigger(), breakLoop() or watch().
374
+ // This section should be really fast to not block threads calling
375
+ // trigger(), breakLoop() or watch().
376
376
if (m_trigger) {
377
377
do_trigger = true ;
378
378
user_trigger = true ;
379
379
m_trigger = false ;
380
380
}
381
+ if (m_user_timeout) {
382
+ do_trigger = true ;
383
+ user_timeout = true ;
384
+ m_user_timeout = false ;
385
+ }
381
386
if (m_update_sets) {
382
387
m_update_sets = false ;
383
388
do_trigger = false ;
@@ -396,6 +401,8 @@ void FileDescriptorActivity::loop()
396
401
step ();
397
402
if (m_has_timeout)
398
403
work (RunnableInterface::TimeOut);
404
+ else if ( user_timeout )
405
+ work (RunnableInterface::TimeOut);
399
406
else if ( user_trigger )
400
407
work (RunnableInterface::Trigger);
401
408
else
@@ -411,13 +418,36 @@ void FileDescriptorActivity::loop()
411
418
}
412
419
}
413
420
421
+ void FileDescriptorActivity::clearInterruptPipe () {
422
+ int pipe = m_interrupt_pipe[0 ];
423
+
424
+ fd_set watch_pipe;
425
+ timeval timeout;
426
+ char dummy;
427
+ do
428
+ {
429
+ int unused; (void )unused;
430
+ unused = read (pipe , &dummy, 1 );
431
+
432
+ // Initialize the values for the next select() call
433
+ FD_ZERO (&watch_pipe);
434
+ FD_SET (m_interrupt_pipe[0 ], &watch_pipe);
435
+ timeout.tv_sec = 0 ;
436
+ timeout.tv_usec = 0 ;
437
+ }
438
+ while (select (pipe + 1 , &watch_pipe, NULL , NULL , &timeout) > 0 );
439
+ }
440
+ void FileDescriptorActivity::writeInterruptPipe () {
441
+ int unused; (void )unused; // avoid the "return value not used" warning
442
+ unused = write (m_interrupt_pipe[1 ], &CMD_ANY_COMMAND, 1 );
443
+ }
444
+
414
445
bool FileDescriptorActivity::breakLoop ()
415
446
{
416
447
{ RTT::os::MutexLock lock (m_command_mutex);
417
448
m_break_loop = true ;
418
449
}
419
- int unused; (void )unused;
420
- unused = write (m_interrupt_pipe[1 ], &CMD_ANY_COMMAND, 1 );
450
+ writeInterruptPipe ();
421
451
return true ;
422
452
}
423
453
0 commit comments