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
19namespace 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.
36class MainLoopBase {
37private:
38 class ReadHandle;
39
40public:
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
65protected:
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
82private:
83 class ReadHandle {
84 public:
85 ~ReadHandle() { m_mainloop.UnregisterReadObject(handle: 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

source code of lldb/include/lldb/Host/MainLoopBase.h