void iothread_perform_on_main(void_function_t &&func) { if (is_main_thread()) { func(); return; } // Make a new request. Note we are synchronous, so this can be stack allocated! main_thread_request_t req(std::move(func)); // Append it. Do not delete the nested scope as it is crucial to the proper functioning of this // code by virtue of the lock management. { scoped_lock queue_lock(s_main_thread_request_q_lock); s_main_thread_request_queue.push(&req); } // Tell the pipe. const char wakeup_byte = IO_SERVICE_MAIN_THREAD_REQUEST_QUEUE; assert_with_errno(write_loop(s_write_pipe, &wakeup_byte, sizeof wakeup_byte) != -1); // Wait on the condition, until we're done. std::unique_lock<std::mutex> perform_lock(s_main_thread_performer_lock); while (!req.done) { // It would be nice to support checking for cancellation here, but the clients need a // deterministic way to clean up to avoid leaks s_main_thread_performer_cond.wait(perform_lock); } // Ok, the request must now be done. assert(req.done); }
int iothread_perform_on_main_base(int (*handler)(void *), void *context) { // If this is the main thread, just do it. if (is_main_thread()) { return handler(context); } // Make a new request. Note we are synchronous, so this can be stack allocated! MainThreadRequest_t req; req.handler = handler; req.context = context; req.handlerResult = 0; req.done = false; // Append it. Do not delete the nested scope as it is crucial to the proper functioning of this // code by virtue of the lock management. { scoped_lock queue_lock(s_main_thread_request_queue_lock); s_main_thread_request_queue.push(&req); } // Tell the pipe. const char wakeup_byte = IO_SERVICE_MAIN_THREAD_REQUEST_QUEUE; VOMIT_ON_FAILURE(!write_loop(s_write_pipe, &wakeup_byte, sizeof wakeup_byte)); // Wait on the condition, until we're done. scoped_lock perform_lock(s_main_thread_performer_lock); while (!req.done) { // It would be nice to support checking for cancellation here, but the clients need a // deterministic way to clean up to avoid leaks VOMIT_ON_FAILURE( pthread_cond_wait(&s_main_thread_performer_condition, &s_main_thread_performer_lock)); } // Ok, the request must now be done. assert(req.done); return req.handlerResult; }