xref: /freebsd/contrib/llvm-project/lldb/include/lldb/Host/MainLoopBase.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===-- MainLoopBase.h ------------------------------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
95ffd83dbSDimitry Andric #ifndef LLDB_HOST_MAINLOOPBASE_H
105ffd83dbSDimitry Andric #define LLDB_HOST_MAINLOOPBASE_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "lldb/Utility/IOObject.h"
130b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
14*bdd1243dSDimitry Andric #include "llvm/ADT/DenseMap.h"
150b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
160b57cec5SDimitry Andric #include <functional>
17*bdd1243dSDimitry Andric #include <mutex>
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric namespace lldb_private {
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric // The purpose of this class is to enable multiplexed processing of data from
220b57cec5SDimitry Andric // different sources without resorting to multi-threading. Clients can register
230b57cec5SDimitry Andric // IOObjects, which will be monitored for readability, and when they become
240b57cec5SDimitry Andric // ready, the specified callback will be invoked. Monitoring for writability is
250b57cec5SDimitry Andric // not supported, but can be easily added if needed.
260b57cec5SDimitry Andric //
270b57cec5SDimitry Andric // The RegisterReadObject function return a handle, which controls the duration
280b57cec5SDimitry Andric // of the monitoring. When this handle is destroyed, the callback is
290b57cec5SDimitry Andric // deregistered.
300b57cec5SDimitry Andric //
31*bdd1243dSDimitry Andric // Since this class is primarily intended to be used for single-threaded
32*bdd1243dSDimitry Andric // processing, it does not attempt to perform any internal synchronisation and
33*bdd1243dSDimitry Andric // any concurrent accesses must be protected  externally. However, it is
34*bdd1243dSDimitry Andric // perfectly legitimate to have more than one instance of this class running on
35*bdd1243dSDimitry Andric // separate threads, or even a single thread.
360b57cec5SDimitry Andric class MainLoopBase {
370b57cec5SDimitry Andric private:
380b57cec5SDimitry Andric   class ReadHandle;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric public:
MainLoopBase()41*bdd1243dSDimitry Andric   MainLoopBase() : m_terminate_request(false) {}
42fe6060f1SDimitry Andric   virtual ~MainLoopBase() = default;
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   typedef std::unique_ptr<ReadHandle> ReadHandleUP;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   typedef std::function<void(MainLoopBase &)> Callback;
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   virtual ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp,
490b57cec5SDimitry Andric                                           const Callback &callback,
50*bdd1243dSDimitry Andric                                           Status &error) = 0;
510b57cec5SDimitry Andric 
5281ad6265SDimitry Andric   // Add a pending callback that will be executed once after all the pending
5381ad6265SDimitry Andric   // events are processed. The callback will be executed even if termination
5481ad6265SDimitry Andric   // was requested.
55*bdd1243dSDimitry Andric   void AddPendingCallback(const Callback &callback);
5681ad6265SDimitry Andric 
570b57cec5SDimitry Andric   // Waits for registered events and invoke the proper callbacks. Returns when
580b57cec5SDimitry Andric   // all callbacks deregister themselves or when someone requests termination.
Run()590b57cec5SDimitry Andric   virtual Status Run() { llvm_unreachable("Not implemented"); }
600b57cec5SDimitry Andric 
61*bdd1243dSDimitry Andric   // This should only be performed from a callback. Do not attempt to terminate
62*bdd1243dSDimitry Andric   // the processing from another thread.
RequestTermination()63*bdd1243dSDimitry Andric   virtual void RequestTermination() { m_terminate_request = true; }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric protected:
CreateReadHandle(const lldb::IOObjectSP & object_sp)660b57cec5SDimitry Andric   ReadHandleUP CreateReadHandle(const lldb::IOObjectSP &object_sp) {
670b57cec5SDimitry Andric     return ReadHandleUP(new ReadHandle(*this, object_sp->GetWaitableHandle()));
680b57cec5SDimitry Andric   }
690b57cec5SDimitry Andric 
70*bdd1243dSDimitry Andric   virtual void UnregisterReadObject(IOObject::WaitableHandle handle) = 0;
71*bdd1243dSDimitry Andric 
72*bdd1243dSDimitry Andric   // Interrupt the loop that is currently waiting for events and execute
73*bdd1243dSDimitry Andric   // the current pending callbacks immediately.
74*bdd1243dSDimitry Andric   virtual void TriggerPendingCallbacks() = 0;
75*bdd1243dSDimitry Andric 
76*bdd1243dSDimitry Andric   void ProcessPendingCallbacks();
77*bdd1243dSDimitry Andric 
78*bdd1243dSDimitry Andric   std::mutex m_callback_mutex;
79*bdd1243dSDimitry Andric   std::vector<Callback> m_pending_callbacks;
80*bdd1243dSDimitry Andric   bool m_terminate_request : 1;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric private:
830b57cec5SDimitry Andric   class ReadHandle {
840b57cec5SDimitry Andric   public:
~ReadHandle()850b57cec5SDimitry Andric     ~ReadHandle() { m_mainloop.UnregisterReadObject(m_handle); }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   private:
ReadHandle(MainLoopBase & mainloop,IOObject::WaitableHandle handle)880b57cec5SDimitry Andric     ReadHandle(MainLoopBase &mainloop, IOObject::WaitableHandle handle)
890b57cec5SDimitry Andric         : m_mainloop(mainloop), m_handle(handle) {}
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric     MainLoopBase &m_mainloop;
920b57cec5SDimitry Andric     IOObject::WaitableHandle m_handle;
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric     friend class MainLoopBase;
955ffd83dbSDimitry Andric     ReadHandle(const ReadHandle &) = delete;
965ffd83dbSDimitry Andric     const ReadHandle &operator=(const ReadHandle &) = delete;
970b57cec5SDimitry Andric   };
980b57cec5SDimitry Andric 
995ffd83dbSDimitry Andric   MainLoopBase(const MainLoopBase &) = delete;
1005ffd83dbSDimitry Andric   const MainLoopBase &operator=(const MainLoopBase &) = delete;
1010b57cec5SDimitry Andric };
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric } // namespace lldb_private
1040b57cec5SDimitry Andric 
1055ffd83dbSDimitry Andric #endif // LLDB_HOST_MAINLOOPBASE_H
106