1 //===-- MainLoopBase.h ------------------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_HOST_MAINLOOPBASE_H 10 #define LLDB_HOST_MAINLOOPBASE_H 11 12 #include "lldb/Utility/IOObject.h" 13 #include "lldb/Utility/Status.h" 14 #include "llvm/ADT/DenseMap.h" 15 #include "llvm/Support/ErrorHandling.h" 16 #include <functional> 17 #include <mutex> 18 19 namespace lldb_private { 20 21 // The purpose of this class is to enable multiplexed processing of data from 22 // different sources without resorting to multi-threading. Clients can register 23 // IOObjects, which will be monitored for readability, and when they become 24 // ready, the specified callback will be invoked. Monitoring for writability is 25 // not supported, but can be easily added if needed. 26 // 27 // The RegisterReadObject function return a handle, which controls the duration 28 // of the monitoring. When this handle is destroyed, the callback is 29 // deregistered. 30 // 31 // Since this class is primarily intended to be used for single-threaded 32 // processing, it does not attempt to perform any internal synchronisation and 33 // any concurrent accesses must be protected externally. However, it is 34 // perfectly legitimate to have more than one instance of this class running on 35 // separate threads, or even a single thread. 36 class MainLoopBase { 37 private: 38 class ReadHandle; 39 40 public: 41 MainLoopBase() : m_terminate_request(false) {} 42 virtual ~MainLoopBase() = default; 43 44 typedef std::unique_ptr<ReadHandle> ReadHandleUP; 45 46 typedef std::function<void(MainLoopBase &)> Callback; 47 48 virtual ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp, 49 const Callback &callback, 50 Status &error) = 0; 51 52 // Add a pending callback that will be executed once after all the pending 53 // events are processed. The callback will be executed even if termination 54 // was requested. 55 void AddPendingCallback(const Callback &callback); 56 57 // Waits for registered events and invoke the proper callbacks. Returns when 58 // all callbacks deregister themselves or when someone requests termination. 59 virtual Status Run() { llvm_unreachable("Not implemented"); } 60 61 // This should only be performed from a callback. Do not attempt to terminate 62 // the processing from another thread. 63 virtual void RequestTermination() { m_terminate_request = true; } 64 65 protected: 66 ReadHandleUP CreateReadHandle(const lldb::IOObjectSP &object_sp) { 67 return ReadHandleUP(new ReadHandle(*this, object_sp->GetWaitableHandle())); 68 } 69 70 virtual void UnregisterReadObject(IOObject::WaitableHandle handle) = 0; 71 72 // Interrupt the loop that is currently waiting for events and execute 73 // the current pending callbacks immediately. 74 virtual void TriggerPendingCallbacks() = 0; 75 76 void ProcessPendingCallbacks(); 77 78 std::mutex m_callback_mutex; 79 std::vector<Callback> m_pending_callbacks; 80 bool m_terminate_request : 1; 81 82 private: 83 class ReadHandle { 84 public: 85 ~ReadHandle() { m_mainloop.UnregisterReadObject(m_handle); } 86 87 private: 88 ReadHandle(MainLoopBase &mainloop, IOObject::WaitableHandle handle) 89 : m_mainloop(mainloop), m_handle(handle) {} 90 91 MainLoopBase &m_mainloop; 92 IOObject::WaitableHandle m_handle; 93 94 friend class MainLoopBase; 95 ReadHandle(const ReadHandle &) = delete; 96 const ReadHandle &operator=(const ReadHandle &) = delete; 97 }; 98 99 MainLoopBase(const MainLoopBase &) = delete; 100 const MainLoopBase &operator=(const MainLoopBase &) = delete; 101 }; 102 103 } // namespace lldb_private 104 105 #endif // LLDB_HOST_MAINLOOPBASE_H 106