diff --git a/src/history.cpp b/src/history.cpp index a3e326976..aa27c7366 100644 --- a/src/history.cpp +++ b/src/history.cpp @@ -1773,7 +1773,7 @@ void history_t::add_pending_with_file_detection(const wcstring &str) { // Kick it off. Even though we haven't added the item yet, it updates the item on the main // thread, so we can't race. - iothread_perform(threaded_perform_file_detection, perform_file_detection_done, context); + iothread_perform(&threaded_perform_file_detection, &perform_file_detection_done, context); } // Actually add the item to the history. diff --git a/src/iothread.cpp b/src/iothread.cpp index 0ed6f52b1..7fe6c9caf 100644 --- a/src/iothread.cpp +++ b/src/iothread.cpp @@ -190,7 +190,7 @@ static void iothread_spawn() { VOMIT_ON_FAILURE(pthread_sigmask(SIG_SETMASK, &saved_set, NULL)); } -int iothread_perform(void_function_t &&func, void_function_t &&completion) { +int iothread_perform_impl(void_function_t &&func, void_function_t &&completion) { ASSERT_IS_MAIN_THREAD(); ASSERT_IS_NOT_FORKED_CHILD(); iothread_init(); diff --git a/src/iothread.h b/src/iothread.h index 5faa477e7..0b26a4209 100644 --- a/src/iothread.h +++ b/src/iothread.h @@ -26,16 +26,42 @@ void iothread_service_completion(void); /// Waits for all iothreads to terminate. void iothread_drain_all(void); -int iothread_perform(std::function &&func, - std::function &&completion = std::function()); +// Internal implementation +int iothread_perform_impl(std::function &&func, + std::function &&completion); -// Variant that allows computing a value in func, and then passing it to the completion handler +// Template helpers template -int iothread_perform(std::function &&handler, std::function &&completion) { - T *result = new T(); - return iothread_perform([=](){ *result = handler(); }, - [=](){ completion(std::move(*result)); delete result; } - ); +struct _iothread_trampoline { + template + static int perform(const HANDLER &handler, const COMPLETION &completion) { + T *result = new T(); + return iothread_perform_impl([=](){ *result = handler(); }, + [=](){ completion(std::move(*result)); delete result; }); + } +}; + + +// Void specialization +template<> +struct _iothread_trampoline { + template + static int perform(const HANDLER &handler, const COMPLETION &completion) { + return iothread_perform_impl(handler, completion); + } +}; + +// iothread_perform invokes a handler on a background thread, and then a completion function +// on the main thread. The value returned from the handler is passed to the completion. +template +int iothread_perform(const HANDLER &handler, const COMPLETION &completion) { + return _iothread_trampoline::perform(handler, completion); +} + +// variant of iothread_perform without a completion handler +inline int iothread_perform(std::function &&func) { + return iothread_perform_impl(std::move(func), + std::function()); } /// Legacy templates diff --git a/src/reader.cpp b/src/reader.cpp index b018a8fcd..de7c50fd9 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -1222,7 +1222,7 @@ static void update_autosuggestion(void) { const editable_line_t *el = data->active_edit_line(); autosuggestion_context_t *ctx = new autosuggestion_context_t(data->history, el->text, el->position); - iothread_perform(threaded_autosuggest, autosuggest_completed, ctx); + iothread_perform(&threaded_autosuggest, &autosuggest_completed, ctx); } } @@ -2178,7 +2178,7 @@ static void reader_super_highlight_me_plenty(int match_highlight_pos_adjust, boo highlight_complete(ctx, result); } else { // Highlighting including I/O proceeds in the background. - iothread_perform(threaded_highlight, highlight_complete, ctx); + iothread_perform(&threaded_highlight, &highlight_complete, ctx); } highlight_search();