xref: /openbsd-src/gnu/llvm/lldb/include/lldb/Host/MainLoopBase.h (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1061da546Spatrick //===-- MainLoopBase.h ------------------------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9dda28197Spatrick #ifndef LLDB_HOST_MAINLOOPBASE_H
10dda28197Spatrick #define LLDB_HOST_MAINLOOPBASE_H
11061da546Spatrick 
12061da546Spatrick #include "lldb/Utility/IOObject.h"
13061da546Spatrick #include "lldb/Utility/Status.h"
14*f6aab3d8Srobert #include "llvm/ADT/DenseMap.h"
15061da546Spatrick #include "llvm/Support/ErrorHandling.h"
16061da546Spatrick #include <functional>
17*f6aab3d8Srobert #include <mutex>
18061da546Spatrick 
19061da546Spatrick namespace lldb_private {
20061da546Spatrick 
21061da546Spatrick // The purpose of this class is to enable multiplexed processing of data from
22061da546Spatrick // different sources without resorting to multi-threading. Clients can register
23061da546Spatrick // IOObjects, which will be monitored for readability, and when they become
24061da546Spatrick // ready, the specified callback will be invoked. Monitoring for writability is
25061da546Spatrick // not supported, but can be easily added if needed.
26061da546Spatrick //
27061da546Spatrick // The RegisterReadObject function return a handle, which controls the duration
28061da546Spatrick // of the monitoring. When this handle is destroyed, the callback is
29061da546Spatrick // deregistered.
30061da546Spatrick //
31*f6aab3d8Srobert // Since this class is primarily intended to be used for single-threaded
32*f6aab3d8Srobert // processing, it does not attempt to perform any internal synchronisation and
33*f6aab3d8Srobert // any concurrent accesses must be protected  externally. However, it is
34*f6aab3d8Srobert // perfectly legitimate to have more than one instance of this class running on
35*f6aab3d8Srobert // separate threads, or even a single thread.
36061da546Spatrick class MainLoopBase {
37061da546Spatrick private:
38061da546Spatrick   class ReadHandle;
39061da546Spatrick 
40061da546Spatrick public:
MainLoopBase()41*f6aab3d8Srobert   MainLoopBase() : m_terminate_request(false) {}
42be691f3bSpatrick   virtual ~MainLoopBase() = default;
43061da546Spatrick 
44061da546Spatrick   typedef std::unique_ptr<ReadHandle> ReadHandleUP;
45061da546Spatrick 
46061da546Spatrick   typedef std::function<void(MainLoopBase &)> Callback;
47061da546Spatrick 
48061da546Spatrick   virtual ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp,
49061da546Spatrick                                           const Callback &callback,
50*f6aab3d8Srobert                                           Status &error) = 0;
51*f6aab3d8Srobert 
52*f6aab3d8Srobert   // Add a pending callback that will be executed once after all the pending
53*f6aab3d8Srobert   // events are processed. The callback will be executed even if termination
54*f6aab3d8Srobert   // was requested.
55*f6aab3d8Srobert   void AddPendingCallback(const Callback &callback);
56061da546Spatrick 
57061da546Spatrick   // Waits for registered events and invoke the proper callbacks. Returns when
58061da546Spatrick   // all callbacks deregister themselves or when someone requests termination.
Run()59061da546Spatrick   virtual Status Run() { llvm_unreachable("Not implemented"); }
60061da546Spatrick 
61*f6aab3d8Srobert   // This should only be performed from a callback. Do not attempt to terminate
62*f6aab3d8Srobert   // the processing from another thread.
RequestTermination()63*f6aab3d8Srobert   virtual void RequestTermination() { m_terminate_request = true; }
64061da546Spatrick 
65061da546Spatrick protected:
CreateReadHandle(const lldb::IOObjectSP & object_sp)66061da546Spatrick   ReadHandleUP CreateReadHandle(const lldb::IOObjectSP &object_sp) {
67061da546Spatrick     return ReadHandleUP(new ReadHandle(*this, object_sp->GetWaitableHandle()));
68061da546Spatrick   }
69061da546Spatrick 
70*f6aab3d8Srobert   virtual void UnregisterReadObject(IOObject::WaitableHandle handle) = 0;
71*f6aab3d8Srobert 
72*f6aab3d8Srobert   // Interrupt the loop that is currently waiting for events and execute
73*f6aab3d8Srobert   // the current pending callbacks immediately.
74*f6aab3d8Srobert   virtual void TriggerPendingCallbacks() = 0;
75*f6aab3d8Srobert 
76*f6aab3d8Srobert   void ProcessPendingCallbacks();
77*f6aab3d8Srobert 
78*f6aab3d8Srobert   std::mutex m_callback_mutex;
79*f6aab3d8Srobert   std::vector<Callback> m_pending_callbacks;
80*f6aab3d8Srobert   bool m_terminate_request : 1;
81061da546Spatrick 
82061da546Spatrick private:
83061da546Spatrick   class ReadHandle {
84061da546Spatrick   public:
~ReadHandle()85061da546Spatrick     ~ReadHandle() { m_mainloop.UnregisterReadObject(m_handle); }
86061da546Spatrick 
87061da546Spatrick   private:
ReadHandle(MainLoopBase & mainloop,IOObject::WaitableHandle handle)88061da546Spatrick     ReadHandle(MainLoopBase &mainloop, IOObject::WaitableHandle handle)
89061da546Spatrick         : m_mainloop(mainloop), m_handle(handle) {}
90061da546Spatrick 
91061da546Spatrick     MainLoopBase &m_mainloop;
92061da546Spatrick     IOObject::WaitableHandle m_handle;
93061da546Spatrick 
94061da546Spatrick     friend class MainLoopBase;
95dda28197Spatrick     ReadHandle(const ReadHandle &) = delete;
96dda28197Spatrick     const ReadHandle &operator=(const ReadHandle &) = delete;
97061da546Spatrick   };
98061da546Spatrick 
99dda28197Spatrick   MainLoopBase(const MainLoopBase &) = delete;
100dda28197Spatrick   const MainLoopBase &operator=(const MainLoopBase &) = delete;
101061da546Spatrick };
102061da546Spatrick 
103061da546Spatrick } // namespace lldb_private
104061da546Spatrick 
105dda28197Spatrick #endif // LLDB_HOST_MAINLOOPBASE_H
106