| 392 | } |
| 393 | |
| 394 | ReactorTask::CommandPtr ReactorTask::execute_or_enqueue(CommandPtr command) |
| 395 | { |
| 396 | OPENDDS_ASSERT(command); |
| 397 | |
| 398 | GuardType guard(lock_); |
| 399 | |
| 400 | // Only allow immediate execution if running on a reactor thread, otherwise we risk deadlock |
| 401 | // when calling into the reactor object. |
| 402 | const bool is_owner = reactor_owners_.find(ACE_Thread::self()) == EXIT_SUCCESS; |
| 403 | |
| 404 | // If state is set to processing, the contents of command_queue_ have been swapped out |
| 405 | // so immediate execution may run jobs out of the expected order. |
| 406 | const bool is_not_processing = !processing_; |
| 407 | |
| 408 | // If the command_queue_ is not empty, allowing execution will potentially run unexpected code |
| 409 | // which is problematic since we may be holding locks used by the unexpected code. |
| 410 | const bool is_empty = command_queue_.empty(); |
| 411 | |
| 412 | // If all three of these conditions are met, it should be safe to execute |
| 413 | const bool is_safe_to_execute = is_owner && is_not_processing && is_empty; |
| 414 | |
| 415 | // Even if it's not normally safe to execute, allow immediate execution if the reactor is shut down |
| 416 | const bool immediate = is_safe_to_execute || (state_ == STATE_SHUT_DOWN); |
| 417 | |
| 418 | // Always set reactor and push to the queue |
| 419 | ACE_Reactor* local_reactor = reactor_; |
| 420 | command_queue_.push_back(command); |
| 421 | |
| 422 | // But depending on whether we're running it immediately or not, we either process or notify |
| 423 | if (immediate) { |
| 424 | process_command_queue_i(); |
| 425 | } else if (!reactor_notified_) { |
| 426 | reactor_notified_ = true; |
| 427 | guard.release(); |
| 428 | local_reactor->notify(this); |
| 429 | } |
| 430 | return command; |
| 431 | } |
| 432 | |
| 433 | void ReactorTask::wait_until_empty() |
| 434 | { |
no test coverage detected