1 /* Run a function on the main thread 2 Copyright (C) 2019-2020 Free Software Foundation, Inc. 3 4 This file is part of GDB. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 19 #include "defs.h" 20 #include "run-on-main-thread.h" 21 #include "ser-event.h" 22 #if CXX_STD_THREAD 23 #include <mutex> 24 #endif 25 #include "gdbsupport/event-loop.h" 26 27 /* The serial event used when posting runnables. */ 28 29 static struct serial_event *runnable_event; 30 31 /* Runnables that have been posted. */ 32 33 static std::vector<std::function<void ()>> runnables; 34 35 #if CXX_STD_THREAD 36 37 /* Mutex to hold when handling RUNNABLE_EVENT or RUNNABLES. */ 38 39 static std::mutex runnable_mutex; 40 41 #endif 42 43 /* Run all the queued runnables. */ 44 45 static void 46 run_events (int error, gdb_client_data client_data) 47 { 48 std::vector<std::function<void ()>> local; 49 50 /* Hold the lock while changing the globals, but not while running 51 the runnables. */ 52 { 53 #if CXX_STD_THREAD 54 std::lock_guard<std::mutex> lock (runnable_mutex); 55 #endif 56 57 /* Clear the event fd. Do this before flushing the events list, 58 so that any new event post afterwards is sure to re-awaken the 59 event loop. */ 60 serial_event_clear (runnable_event); 61 62 /* Move the vector in case running a runnable pushes a new 63 runnable. */ 64 local = std::move (runnables); 65 } 66 67 for (auto &item : local) 68 { 69 try 70 { 71 item (); 72 } 73 catch (...) 74 { 75 /* Ignore exceptions in the callback. */ 76 } 77 } 78 } 79 80 /* See run-on-main-thread.h. */ 81 82 void 83 run_on_main_thread (std::function<void ()> &&func) 84 { 85 #if CXX_STD_THREAD 86 std::lock_guard<std::mutex> lock (runnable_mutex); 87 #endif 88 runnables.emplace_back (std::move (func)); 89 serial_event_set (runnable_event); 90 } 91 92 void _initialize_run_on_main_thread (); 93 void 94 _initialize_run_on_main_thread () 95 { 96 runnable_event = make_serial_event (); 97 add_file_handler (serial_event_fd (runnable_event), run_events, nullptr); 98 } 99