Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:42:49

0001 //===-- MainLoopBase.h ------------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 
0009 #ifndef LLDB_HOST_MAINLOOPBASE_H
0010 #define LLDB_HOST_MAINLOOPBASE_H
0011 
0012 #include "lldb/Utility/IOObject.h"
0013 #include "lldb/Utility/Status.h"
0014 #include "llvm/ADT/DenseMap.h"
0015 #include "llvm/Support/ErrorHandling.h"
0016 #include <chrono>
0017 #include <functional>
0018 #include <mutex>
0019 #include <queue>
0020 
0021 namespace lldb_private {
0022 
0023 // The purpose of this class is to enable multiplexed processing of data from
0024 // different sources without resorting to multi-threading. Clients can register
0025 // IOObjects, which will be monitored for readability, and when they become
0026 // ready, the specified callback will be invoked. Monitoring for writability is
0027 // not supported, but can be easily added if needed.
0028 //
0029 // The RegisterReadObject function return a handle, which controls the duration
0030 // of the monitoring. When this handle is destroyed, the callback is
0031 // deregistered.
0032 //
0033 // Since this class is primarily intended to be used for single-threaded
0034 // processing, it does not attempt to perform any internal synchronisation and
0035 // any concurrent accesses must be protected  externally. However, it is
0036 // perfectly legitimate to have more than one instance of this class running on
0037 // separate threads, or even a single thread.
0038 class MainLoopBase {
0039 private:
0040   class ReadHandle;
0041 
0042 public:
0043   using TimePoint = std::chrono::time_point<std::chrono::steady_clock,
0044                                             std::chrono::nanoseconds>;
0045 
0046   MainLoopBase() : m_terminate_request(false) {}
0047   virtual ~MainLoopBase() = default;
0048 
0049   typedef std::unique_ptr<ReadHandle> ReadHandleUP;
0050 
0051   typedef std::function<void(MainLoopBase &)> Callback;
0052 
0053   virtual ReadHandleUP RegisterReadObject(const lldb::IOObjectSP &object_sp,
0054                                           const Callback &callback,
0055                                           Status &error) = 0;
0056 
0057   // Add a pending callback that will be executed once after all the pending
0058   // events are processed. The callback will be executed even if termination
0059   // was requested.
0060   void AddPendingCallback(const Callback &callback) {
0061     AddCallback(callback, std::chrono::steady_clock::time_point());
0062   }
0063 
0064   // Add a callback that will be executed after a certain amount of time has
0065   // passed.
0066   void AddCallback(const Callback &callback, std::chrono::nanoseconds delay) {
0067     AddCallback(callback, std::chrono::steady_clock::now() + delay);
0068   }
0069 
0070   // Add a callback that will be executed after a given point in time.
0071   void AddCallback(const Callback &callback, TimePoint point);
0072 
0073   // Waits for registered events and invoke the proper callbacks. Returns when
0074   // all callbacks deregister themselves or when someone requests termination.
0075   virtual Status Run() { llvm_unreachable("Not implemented"); }
0076 
0077   // This should only be performed from a callback. Do not attempt to terminate
0078   // the processing from another thread.
0079   virtual void RequestTermination() { m_terminate_request = true; }
0080 
0081 protected:
0082   ReadHandleUP CreateReadHandle(const lldb::IOObjectSP &object_sp) {
0083     return ReadHandleUP(new ReadHandle(*this, object_sp->GetWaitableHandle()));
0084   }
0085 
0086   virtual void UnregisterReadObject(IOObject::WaitableHandle handle) = 0;
0087 
0088   // Interrupt the loop that is currently waiting for events.
0089   virtual void Interrupt() = 0;
0090 
0091   void ProcessCallbacks();
0092 
0093   std::optional<TimePoint> GetNextWakeupTime();
0094 
0095   std::mutex m_callback_mutex;
0096   std::priority_queue<std::pair<TimePoint, Callback>,
0097                       std::vector<std::pair<TimePoint, Callback>>,
0098                       llvm::on_first<std::greater<TimePoint>>>
0099       m_callbacks;
0100   bool m_terminate_request : 1;
0101 
0102 private:
0103   class ReadHandle {
0104   public:
0105     ~ReadHandle() { m_mainloop.UnregisterReadObject(m_handle); }
0106 
0107   private:
0108     ReadHandle(MainLoopBase &mainloop, IOObject::WaitableHandle handle)
0109         : m_mainloop(mainloop), m_handle(handle) {}
0110 
0111     MainLoopBase &m_mainloop;
0112     IOObject::WaitableHandle m_handle;
0113 
0114     friend class MainLoopBase;
0115     ReadHandle(const ReadHandle &) = delete;
0116     const ReadHandle &operator=(const ReadHandle &) = delete;
0117   };
0118 
0119   MainLoopBase(const MainLoopBase &) = delete;
0120   const MainLoopBase &operator=(const MainLoopBase &) = delete;
0121 };
0122 
0123 } // namespace lldb_private
0124 
0125 #endif // LLDB_HOST_MAINLOOPBASE_H