RADLib
RADical C++ application framework
RADCore.h
Go to the documentation of this file.
1 #ifndef RADCORE_H
2 #define RADCORE_H
3 
10 #pragma once
11 #include <RADCore/RADLicenseGate.h>
12 #include <iostream>
13 #include <array>
14 #include <vector>
15 #include <functional>
16 #include <queue>
17 #include <mutex>
18 #include <map>
19 #include <chrono>
20 #include <thread>
21 #include <atomic>
22 #include <memory>
23 #include <algorithm>
24 #include <cstdint>
25 #include <sstream>
26 #include <shared_mutex>
27 #include <future>
28 #include <type_traits>
29 #include <optional>
30 #include <string>
31 #include <filesystem>
32 #include <variant>
33 #include <condition_variable>
34 #include <deque>
35 #include <unordered_map>
36 #include <exception>
37 #include <sys/types.h>
38 
39 // ==========================================================
40 // RADICAL COMPUTER TECHNOLOGIES - MACRO SUITE
41 // ==========================================================
43 #define RADEvents public
45 #define RADHandlers public
46 
48 #define RADInfo() RADCore::Internal::LogStream(RADCore::LogLevel::INFO)
50 #define RADDebug() RADCore::Internal::LogStream(RADCore::LogLevel::DEBUG)
51 
52 #ifndef RADCORE_VERSION_MAJOR
53 #define RADCORE_VERSION_MAJOR 1
54 #endif
55 
56 #ifndef RADCORE_VERSION_MINOR
57 #define RADCORE_VERSION_MINOR 0
58 #endif
59 
60 #ifndef RADCORE_VERSION_PATCH
61 #define RADCORE_VERSION_PATCH 0
62 #endif
63 
65 #define RAD_EVENT(Name, Signature) RADCore::Event<void Signature> Name
66 
68 #define RADCONNECT(Sender, RadEvent, Receiver, Class, RadEventHandler) \
69  (Sender).RadEvent.connect(Receiver, &Class::RadEventHandler)
70 
72 #define RADCONNECT_QUEUED(Sender, RadEvent, Loop, Receiver, Class, RadEventHandler) \
73  (Sender).RadEvent.connect_queued(Loop, Receiver, &Class::RadEventHandler)
74 
76 #define radtrig(RadEvent, ...) RadEvent.raise(__VA_ARGS__)
77 
79 #define rtrig RADCore::Internal::TriggerHelper() <<
80 
81 namespace RADCore {
82 
84  constexpr int VersionMajor = RADCORE_VERSION_MAJOR;
86  constexpr int VersionMinor = RADCORE_VERSION_MINOR;
88  const char* runtimeEdition();
92  const char* runtimeAuditStamp();
93 
95  class RADObject;
97  class EventLoop;
99  class EventLoopHandle;
101  class Connection;
102 
104  class RADError {
105  public:
107  RADError() = default;
109  RADError(int code, std::string message)
110  : code_(code), message_(std::move(message)) {}
111 
113  bool hasError() const { return code_ != 0 || !message_.empty(); }
115  int code() const { return code_; }
117  const std::string& message() const { return message_; }
118 
119  private:
120  int code_ = 0;
121  std::string message_;
122  };
123 
125  template<typename T>
126  class RADResult {
127  public:
129  static RADResult success(T value) { return RADResult(std::move(value)); }
131  static RADResult failure(RADError error) { return RADResult(std::move(error)); }
132 
134  bool ok() const { return value_.has_value(); }
136  bool hasError() const { return !ok(); }
138  T& value() { return *value_; }
140  const T& value() const { return *value_; }
142  const RADError& error() const { return error_; }
144  T valueOr(T defaultValue) const { return value_ ? *value_ : std::move(defaultValue); }
145 
146  private:
147  explicit RADResult(T value) : value_(std::move(value)) {}
148  explicit RADResult(RADError error) : error_(std::move(error)) {}
149 
150  std::optional<T> value_;
151  RADError error_;
152  };
153 
155  template<>
156  class RADResult<void> {
157  public:
159  static RADResult success() { return RADResult(); }
161  static RADResult failure(RADError error) { return RADResult(std::move(error)); }
163  bool ok() const { return !error_.hasError(); }
165  bool hasError() const { return error_.hasError(); }
167  const RADError& error() const { return error_; }
168 
169  private:
170  RADResult() = default;
171  explicit RADResult(RADError error) : error_(std::move(error)) {}
172  RADError error_;
173  };
174 
176  template<typename T>
177  class RADSpan {
178  public:
180  RADSpan() = default;
182  RADSpan(T* data, size_t size) : data_(data), size_(size) {}
184  template<typename Container>
185  explicit RADSpan(Container& container) : data_(container.data()), size_(container.size()) {}
186 
188  T* data() const { return data_; }
190  size_t size() const { return size_; }
192  bool empty() const { return size_ == 0; }
194  T& operator[](size_t index) const { return data_[index]; }
196  T* begin() const { return data_; }
198  T* end() const { return data_ + size_; }
199 
200  private:
201  T* data_ = nullptr;
202  size_t size_ = 0;
203  };
204 
209 
212  public:
216  void restart() { start_ = std::chrono::steady_clock::now(); }
218  int64_t elapsedNanoseconds() const {
219  return std::chrono::duration_cast<std::chrono::nanoseconds>(
220  std::chrono::steady_clock::now() - start_).count();
221  }
223  int64_t elapsedMicroseconds() const { return elapsedNanoseconds() / 1000; }
225  int64_t elapsedMilliseconds() const { return elapsedNanoseconds() / 1000000; }
227  double elapsedSeconds() const { return static_cast<double>(elapsedNanoseconds()) / 1000000000.0; }
228 
229  private:
230  std::chrono::steady_clock::time_point start_;
231  };
232 
235  public:
237  RADDeadlineTimer() = default;
239  explicit RADDeadlineTimer(int64_t intervalMs)
240  : deadline_(std::chrono::steady_clock::now() + std::chrono::milliseconds(intervalMs)),
241  valid_(true) {}
243  bool isValid() const { return valid_; }
245  bool hasExpired() const { return valid_ && std::chrono::steady_clock::now() >= deadline_; }
247  int64_t remainingMilliseconds() const {
248  if (!valid_) return 0;
249  const auto now = std::chrono::steady_clock::now();
250  if (now >= deadline_) return 0;
251  return std::chrono::duration_cast<std::chrono::milliseconds>(deadline_ - now).count();
252  }
253 
254  private:
255  std::chrono::steady_clock::time_point deadline_{};
256  bool valid_ = false;
257  };
258 
261  public:
263  RADCancellationToken() : cancelled_(std::make_shared<std::atomic_bool>(false)) {}
265  bool isCancellationRequested() const {
266  return cancelled_ && cancelled_->load(std::memory_order_acquire);
267  }
268 
269  private:
270  friend class RADCancellationSource;
271  explicit RADCancellationToken(std::shared_ptr<std::atomic_bool> cancelled)
272  : cancelled_(std::move(cancelled)) {}
273  std::shared_ptr<std::atomic_bool> cancelled_;
274  };
275 
278  public:
280  RADCancellationSource() : cancelled_(std::make_shared<std::atomic_bool>(false)) {}
282  RADCancellationToken token() const { return RADCancellationToken(cancelled_); }
284  void cancel() { cancelled_->store(true, std::memory_order_release); }
286  bool isCancellationRequested() const { return cancelled_->load(std::memory_order_acquire); }
287 
288  private:
289  std::shared_ptr<std::atomic_bool> cancelled_;
290  };
291 
293  enum class OpenMode : uint32_t {
295  NotOpen = 0,
297  ReadOnly = 1 << 0,
299  WriteOnly = 1 << 1,
301  ReadWrite = (1 << 0) | (1 << 1),
303  Append = 1 << 2,
305  Truncate = 1 << 3,
307  Text = 1 << 4
308  };
309 
311  constexpr OpenMode operator|(OpenMode lhs, OpenMode rhs) {
312  return static_cast<OpenMode>(
313  static_cast<uint32_t>(lhs) | static_cast<uint32_t>(rhs));
314  }
315 
317  constexpr OpenMode operator&(OpenMode lhs, OpenMode rhs) {
318  return static_cast<OpenMode>(
319  static_cast<uint32_t>(lhs) & static_cast<uint32_t>(rhs));
320  }
321 
323  constexpr bool hasOpenMode(OpenMode mode, OpenMode flag) {
324  return (static_cast<uint32_t>(mode) & static_cast<uint32_t>(flag)) != 0;
325  }
326 
328  enum class ByteOrder {
330  LittleEndian,
332  BigEndian
333  };
334 
336  enum class DataStreamStatus {
338  Ok,
340  ReadPastEnd,
342  WriteFailed,
344  ReadFailed
345  };
346 
348  enum class VariantType {
350  Invalid,
352  Bool,
354  Int64,
356  Double,
358  String,
360  ByteArray
361  };
362 
364  class RADVariant {
365  public:
369  RADVariant(bool value);
371  RADVariant(int value);
373  RADVariant(int64_t value);
375  RADVariant(double value);
377  RADVariant(const char* value);
379  RADVariant(std::string value);
381  RADVariant(std::vector<uint8_t> value);
382 
384  VariantType type() const;
386  bool isValid() const;
388  bool toBool(bool defaultValue = false) const;
390  int64_t toInt64(int64_t defaultValue = 0) const;
392  double toDouble(double defaultValue = 0.0) const;
394  std::string toString(const std::string& defaultValue = {}) const;
396  std::vector<uint8_t> toByteArray() const;
397 
398  private:
399  using Storage = std::variant<std::monostate, bool, int64_t, double, std::string, std::vector<uint8_t>>;
400  Storage data_;
401  };
402 
404  class RADDateTime {
405  public:
409  explicit RADDateTime(int64_t unixMilliseconds);
410 
412  static RADDateTime nowUtc();
414  static RADDateTime fromUnixMilliseconds(int64_t unixMilliseconds);
416  static std::optional<RADDateTime> fromIsoString(const std::string& isoString);
417 
419  int64_t toUnixMilliseconds() const;
421  std::string toIsoString() const;
423  bool isValid() const;
424 
425  private:
426  int64_t unixMilliseconds_ = 0;
427  bool valid_ = false;
428  };
429 
431  class RADUuid {
432  public:
436  explicit RADUuid(std::array<uint8_t, 16> bytes);
437 
439  static RADUuid createUuid();
441  static std::optional<RADUuid> fromString(const std::string& text);
442 
444  std::string toString() const;
446  bool isNull() const;
448  const std::array<uint8_t, 16>& bytes() const;
449 
450  private:
451  std::array<uint8_t, 16> bytes_{};
452  };
453 
455  class RADUrl {
456  public:
458  RADUrl() = default;
460  explicit RADUrl(std::string url);
461 
463  static std::optional<RADUrl> parse(const std::string& url);
464 
466  bool isValid() const;
468  const std::string& scheme() const;
470  const std::string& host() const;
472  uint16_t port(uint16_t defaultPort = 0) const;
474  const std::string& path() const;
476  const std::string& query() const;
478  const std::string& fragment() const;
480  std::string toString() const;
481 
482  private:
483  bool valid_ = false;
484  std::string scheme_;
485  std::string host_;
486  uint16_t port_ = 0;
487  std::string path_ = "/";
488  std::string query_;
489  std::string fragment_;
490  };
491 
493  enum class JsonType {
495  Null,
497  Bool,
499  Number,
501  String,
503  Array,
505  Object
506  };
507 
509  class RADJsonValue {
510  public:
514  RADJsonValue(std::nullptr_t);
516  RADJsonValue(bool value);
518  RADJsonValue(int value);
520  RADJsonValue(int64_t value);
522  RADJsonValue(double value);
524  RADJsonValue(const char* value);
526  RADJsonValue(std::string value);
528  RADJsonValue(const RADJsonValue& other);
530  RADJsonValue(RADJsonValue&& other) noexcept = default;
534  RADJsonValue& operator=(RADJsonValue&& other) noexcept = default;
535 
537  static RADJsonValue array();
540 
542  JsonType type() const;
544  bool isNull() const;
546  bool isBool() const;
548  bool isNumber() const;
550  bool isString() const;
552  bool isArray() const;
554  bool isObject() const;
555 
557  bool toBool(bool defaultValue = false) const;
559  double toNumber(double defaultValue = 0.0) const;
561  int toInt(int defaultValue = 0) const;
563  int64_t toInt64(int64_t defaultValue = 0) const;
565  std::string toString(const std::string& defaultValue = {}) const;
566 
568  size_t size() const;
570  bool contains(const std::string& key) const;
572  std::vector<std::string> keys() const;
574  void append(RADJsonValue value);
576  void remove(const std::string& key);
577 
579  RADJsonValue& operator[](const std::string& key);
581  const RADJsonValue& operator[](const std::string& key) const;
583  RADJsonValue& operator[](size_t index);
585  const RADJsonValue& operator[](size_t index) const;
586 
588  std::string toJson(bool pretty = false, int indent = 0) const;
589 
590  private:
591  struct ArrayData;
592  struct ObjectData;
593 
594  using Storage = std::variant<
595  std::nullptr_t,
596  bool,
597  int64_t,
598  double,
599  std::string,
600  std::shared_ptr<ArrayData>,
601  std::shared_ptr<ObjectData>>;
602 
603  void ensureArray();
604  void ensureObject();
605  const ArrayData* arrayData() const;
606  ArrayData* arrayData();
607  const ObjectData* objectData() const;
608  ObjectData* objectData();
609  static Storage cloneStorage(const Storage& storage);
610  static const RADJsonValue& nullValue();
611 
612  Storage data_;
613  };
614 
617  public:
622 
624  static std::optional<RADJsonDocument> fromJson(const std::string& json, std::string* error = nullptr);
626  static std::optional<RADJsonDocument> fromFile(const std::string& path, std::string* error = nullptr);
627 
629  const RADJsonValue& root() const;
633  std::string toJson(bool pretty = false) const;
635  bool toFile(const std::string& path, bool pretty = true, std::string* error = nullptr) const;
636 
637  private:
638  RADJsonValue root_;
639  };
640 
642  class RADSettings {
643  public:
645  explicit RADSettings(std::string fileName);
646 
648  const std::string& fileName() const;
650  bool load(std::string* error = nullptr);
652  bool save(std::string* error = nullptr) const;
654  bool contains(const std::string& key) const;
656  RADJsonValue value(const std::string& key, RADJsonValue defaultValue = {}) const;
658  void setValue(const std::string& key, RADJsonValue value);
660  void remove(const std::string& key);
662  void clear();
663 
664  private:
665  std::string fileName_;
666  RADJsonValue root_;
667  };
668 
670  namespace FileSystem {
672  enum class StandardPath {
674  Home,
676  Desktop,
678  Documents,
680  Downloads,
682  Config,
684  Data,
686  Cache,
688  Temp,
690  Executable,
692  Current
693  };
694 
696  enum class DirectoryEntryType {
698  Unknown,
700  File,
702  Directory,
704  Symlink
705  };
706 
708  struct DirectoryEntry {
710  std::string path;
712  std::string name;
716  uintmax_t size = 0;
718  int64_t modifiedUnixMs = 0;
719  };
720 
722  bool exists(const std::string& path);
724  bool isFile(const std::string& path);
726  bool isDirectory(const std::string& path);
728  bool createDirectories(const std::string& path);
730  bool remove(const std::string& path);
732  bool copyFile(const std::string& source, const std::string& destination, bool overwrite = true);
734  std::string currentPath();
736  std::string tempDirectoryPath();
738  std::string standardPath(StandardPath path);
740  std::string fileName(const std::string& path);
742  std::string extension(const std::string& path);
744  std::string parentPath(const std::string& path);
746  std::vector<DirectoryEntry> listEntries(const std::string& path, bool recursive = false);
748  std::vector<std::string> listDirectory(const std::string& path);
750  std::string mimeTypeForFile(const std::string& path);
752  std::optional<std::string> readTextFile(const std::string& path);
754  bool writeTextFile(const std::string& path, const std::string& text);
755  }
756 
759  public:
761  explicit RADTemporaryDirectory(std::string prefix = "radlib");
764 
773 
775  bool isValid() const;
777  const std::string& path() const;
779  void setAutoRemove(bool enabled);
781  bool autoRemove() const;
783  bool remove();
784 
785  private:
786  std::string path_;
787  bool autoRemove_ = true;
788  };
789 
792  public:
794  explicit RADTemporaryFile(std::string prefix = "radlib");
797 
806 
808  bool isValid() const;
810  const std::string& fileName() const;
812  int fd() const;
814  void setAutoRemove(bool enabled);
816  bool autoRemove() const;
818  bool remove();
819 
820  private:
821  std::string fileName_;
822  int fd_ = -1;
823  bool autoRemove_ = true;
824  };
825 
827  class RADLockFile {
828  public:
830  explicit RADLockFile(std::string fileName);
833 
835  RADLockFile(const RADLockFile&) = delete;
837  RADLockFile& operator=(const RADLockFile&) = delete;
838 
840  bool tryLock();
842  void unlock();
844  bool isLocked() const;
846  const std::string& fileName() const;
847 
848  private:
849  std::string fileName_;
850  int fd_ = -1;
851  };
852 
854  enum class ProcessState {
856  NotRunning,
858  Running,
860  Finished,
863  };
864 
866  struct ThreadAffinity {
868  std::thread::id threadId;
871  };
872 
874  template<typename Signature> class Event;
875 
876  namespace Internal {
877  template<typename T> struct ExtractArgs;
878  template<typename Ret, typename... Args>
879  struct ExtractArgs<Ret(*)(Args...)> { using type = void(Args...); };
880 
881  template<typename... Args> struct EventBinder;
882  struct TriggerHelper;
883  }
884 
892  enum class Priority : int { LOW = 0, NORMAL = 1, HIGH = 2 };
893 
897  size_t connectionId;
899  std::function<void()> disconnectCallback;
900  };
901 
903  class Connection {
904  public:
906  struct State {
908  std::atomic_bool connected{false};
910  std::function<void()> disconnectCallback;
911  };
912 
914  Connection() = default;
915 
917  void disconnect();
919  bool isConnected() const;
920 
921  private:
922  explicit Connection(std::shared_ptr<State> state);
923  static Connection create(std::function<void()> disconnectCallback);
924 
925  std::shared_ptr<State> state_;
926 
927  template<typename Signature> friend class Event;
928  };
929 
931  class RADObject {
932  public:
936  virtual ~RADObject();
938  void registerLink(const ConnectionRecord& record);
939 
941  std::thread::id threadId() const;
947  std::weak_ptr<void> lifetimeToken() const;
949  void moveToThread(std::thread::id tId, EventLoop* loop = nullptr);
950  private:
951  struct Impl;
952  std::unique_ptr<Impl> pImpl;
953  };
954 
956  class EventLoop {
957  public:
959  using Task = std::function<void()>;
964 
966  void post(Priority priority, Task task);
968  void post(Task task);
972  void exec();
974  void quit();
976  bool isEventThread() const;
980  bool postDelayed(int delayMs, Task task);
981 
983  template<typename F, typename... Args>
984  void post(Priority priority, F&& f, Args&&... args) {
985  auto boundTask = [f = std::forward<F>(f), ...args = std::forward<Args>(args)]() mutable {
986  f(std::forward<Args>(args)...);
987  };
988  post(priority, Task(boundTask));
989  }
990 
992  template<typename F, typename... Args>
993  void post(F&& f, Args&&... args) {
994  auto boundTask = [f = std::forward<F>(f), ...args = std::forward<Args>(args)]() mutable {
995  f(std::forward<Args>(args)...);
996  };
997  post(Task(boundTask));
998  }
999 
1000  private:
1001  struct Impl;
1002  friend class EventLoopHandle;
1003  std::shared_ptr<Impl> pImpl;
1004  };
1005 
1008  public:
1010  EventLoopHandle() = default;
1012  bool isValid() const;
1014  bool post(Priority priority, EventLoop::Task task) const;
1016  bool post(EventLoop::Task task) const;
1018  bool postDelayed(int delayMs, EventLoop::Task task) const;
1019 
1020  private:
1021  friend class EventLoop;
1022  explicit EventLoopHandle(std::weak_ptr<EventLoop::Impl> impl);
1023  std::weak_ptr<EventLoop::Impl> impl_;
1024  };
1025 
1027  void singleShot(int intervalMs, EventLoop& targetLoop, EventLoop::Task task);
1028 
1030  template<typename F>
1031  void invoke(EventLoop& loop, F&& task) {
1032  loop.post(std::forward<F>(task));
1033  }
1034 
1036  template<typename F>
1037  auto invokeBlocking(EventLoop& loop, F&& task) -> std::invoke_result_t<F> {
1038  using ReturnType = std::invoke_result_t<F>;
1039 
1040  if (loop.isEventThread()) {
1041  if constexpr (std::is_void_v<ReturnType>) {
1042  std::forward<F>(task)();
1043  return;
1044  } else {
1045  return std::forward<F>(task)();
1046  }
1047  }
1048 
1049  auto promise = std::make_shared<std::promise<ReturnType>>();
1050  auto future = promise->get_future();
1051  auto taskPtr = std::make_shared<std::decay_t<F>>(std::forward<F>(task));
1052 
1053  loop.post([promise, taskPtr]() mutable {
1054  try {
1055  if constexpr (std::is_void_v<ReturnType>) {
1056  (*taskPtr)();
1057  promise->set_value();
1058  } else {
1059  promise->set_value((*taskPtr)());
1060  }
1061  } catch (...) {
1062  promise->set_exception(std::current_exception());
1063  }
1064  });
1065 
1066  if constexpr (std::is_void_v<ReturnType>) {
1067  future.get();
1068  return;
1069  } else {
1070  return future.get();
1071  }
1072  }
1073 
1076  public:
1078  using RawTask = std::function<void()>;
1079 
1081  void addRawHandler(size_t id, RawTask task);
1083  void removeRawHandler(size_t id);
1085  void invokeAll();
1086  private:
1087  struct BackendSlot { size_t id; RawTask task; };
1088  std::vector<BackendSlot> rawHandlers_;
1089  std::mutex backendMutex_;
1090  };
1091 
1093  template<typename... Args>
1094  class Event<void(Args...)> {
1095  public:
1097  struct LiveHandler {
1099  size_t id;
1101  std::function<void(Args...)> dispatch;
1103  std::shared_ptr<Connection::State> connectionState;
1104  };
1105 
1107  Event() : aliveToken_(std::make_shared<std::atomic_bool>(true)) {}
1108 
1111  // Explicitly invalidate our token to instantly tell all bound receivers that this event is dead!
1112  aliveToken_->store(false, std::memory_order_release);
1113  std::lock_guard<std::mutex> lock(eventMutex_);
1114  for (const auto& handler : handlers_) {
1115  if (handler.connectionState) {
1116  handler.connectionState->connected.store(false, std::memory_order_release);
1117  }
1118  }
1119  }
1120 
1122  template<typename T>
1123  Connection connect(T* receiver, void(T::*memberFunc)(Args...)) {
1124  size_t uniqueId = generateUniqueId();
1125  RADObject* baseReceiver = static_cast<RADObject*>(receiver);
1126 
1127  auto receiverToken = baseReceiver->lifetimeToken();
1128  auto dispatchBridge = [receiverToken, receiver, memberFunc, baseReceiver](Args... args) {
1129  auto receiverLife = receiverToken.lock();
1130  if (!receiverLife) return;
1131 
1132  const ThreadAffinity affinity = baseReceiver->threadAffinity();
1133  if (affinity.threadId == std::this_thread::get_id()) {
1134  (receiver->*memberFunc)(args...);
1135  } else {
1136  EventLoop* targetLoop = affinity.eventLoop;
1137  if (targetLoop) {
1138  targetLoop->post([receiverToken, receiver, memberFunc, ...args = std::forward<Args>(args)]() mutable {
1139  auto queuedReceiverLife = receiverToken.lock();
1140  if (!queuedReceiverLife) return;
1141  (receiver->*memberFunc)(std::forward<Args>(args)...);
1142  });
1143  } else {
1144  (receiver->*memberFunc)(args...);
1145  }
1146  }
1147  };
1148 
1149  backend_.addRawHandler(uniqueId, [this]() {});
1150 
1151  auto token = aliveToken_;
1152  Connection connection = Connection::create([this, uniqueId, token]() {
1153  if (token->load(std::memory_order_acquire)) {
1154  this->disconnect(uniqueId);
1155  }
1156  });
1157 
1158  {
1159  std::lock_guard<std::mutex> lock(eventMutex_);
1160  handlers_.push_back({
1161  uniqueId,
1162  [dispatchBridge](Args... args) { dispatchBridge(args...); },
1163  connection.state_
1164  });
1165  }
1166 
1167  // Capture a copy of our aliveToken inside the registration block!
1168  baseReceiver->registerLink({ uniqueId, [connection]() mutable {
1169  connection.disconnect();
1170  }});
1171 
1172  return connection;
1173  }
1174 
1176  template<typename T>
1177  Connection connect_queued(EventLoop& loop, T* receiver, void(T::*memberFunc)(Args...)) {
1178  size_t uniqueId = generateUniqueId();
1179  RADObject* baseObject = static_cast<RADObject*>(receiver);
1180  auto receiverToken = baseObject->lifetimeToken();
1181 
1182  auto cb = [&loop, receiverToken, receiver, memberFunc](Args... args) {
1183  loop.post([receiverToken, receiver, memberFunc, ...args = std::forward<Args>(args)]() mutable {
1184  auto receiverLife = receiverToken.lock();
1185  if (!receiverLife) return;
1186  (receiver->*memberFunc)(std::forward<Args>(args)...);
1187  });
1188  };
1189 
1190  backend_.addRawHandler(uniqueId, [cb]() {});
1191 
1192  auto token = aliveToken_;
1193  Connection connection = Connection::create([&loop, this, uniqueId, token]() {
1194  if (token->load(std::memory_order_acquire)) {
1195  loop.post(Priority::HIGH, [this, uniqueId]() { this->disconnect(uniqueId); });
1196  }
1197  });
1198 
1199  {
1200  std::lock_guard<std::mutex> lock(eventMutex_);
1201  handlers_.push_back({
1202  uniqueId,
1203  [cb](Args... args) { cb(args...); },
1204  connection.state_
1205  });
1206  }
1207 
1208  baseObject->registerLink({ uniqueId, [connection]() mutable {
1209  connection.disconnect();
1210  }});
1211 
1212  return connection;
1213  }
1214 
1216  void disconnect(size_t targetId) {
1217  std::lock_guard<std::mutex> lock(eventMutex_);
1218  for (const auto& handler : handlers_) {
1219  if (handler.id == targetId && handler.connectionState) {
1220  handler.connectionState->connected.store(false, std::memory_order_release);
1221  }
1222  }
1223  handlers_.erase(std::remove_if(handlers_.begin(), handlers_.end(), [targetId](const LiveHandler& handler) {
1224  return handler.id == targetId;
1225  }), handlers_.end());
1226  backend_.removeRawHandler(targetId);
1227  }
1228 
1230  void raise(Args... args) {
1231  std::vector<std::function<void(Args...)>> localHandlers;
1232  {
1233  std::lock_guard<std::mutex> lock(eventMutex_);
1234  localHandlers.reserve(handlers_.size());
1235  for (const auto& handler : handlers_) {
1236  localHandlers.push_back(handler.dispatch);
1237  }
1238  }
1239  for (const auto& handler : localHandlers) {
1240  if (handler) handler(args...);
1241  }
1242  backend_.invokeAll();
1243  }
1244 
1245  private:
1246  size_t generateUniqueId() { static std::atomic<size_t> s_counter{0}; return s_counter++; }
1247  std::vector<LiveHandler> handlers_;
1248  std::mutex eventMutex_;
1249  EventBackend backend_;
1250  std::shared_ptr<std::atomic_bool> aliveToken_; // Token tracking emitter lifespan state parameters
1251  };
1252 
1254  class RADIODevice : public RADObject {
1255  public:
1256  RADEvents:
1258  RAD_EVENT(readyRead, ());
1260  RAD_EVENT(bytesWritten, (size_t));
1262  RAD_EVENT(errorOccurred, (std::string));
1263 
1265  virtual ~RADIODevice() = default;
1266 
1268  virtual bool open(OpenMode mode) = 0;
1270  virtual void close() = 0;
1272  virtual bool isOpen() const = 0;
1274  virtual ssize_t readData(void* buffer, size_t maxBytes) = 0;
1276  virtual ssize_t writeData(const void* data, size_t size) = 0;
1277 
1279  std::vector<uint8_t> read(size_t maxBytes);
1281  std::vector<uint8_t> readAll(size_t chunkSize = 8192);
1283  ssize_t write(const std::vector<uint8_t>& data);
1285  ssize_t write(const std::string& text);
1286  };
1287 
1289  class RADBuffer : public RADIODevice {
1290  public:
1294  explicit RADBuffer(std::vector<uint8_t> data);
1296  ~RADBuffer() override;
1297 
1299  bool open(OpenMode mode) override;
1301  void close() override;
1303  bool isOpen() const override;
1305  ssize_t readData(void* buffer, size_t maxBytes) override;
1307  ssize_t writeData(const void* data, size_t size) override;
1308 
1310  bool seek(size_t position);
1312  size_t position() const;
1314  size_t size() const;
1316  const std::vector<uint8_t>& data() const;
1318  void clear();
1319 
1320  private:
1321  struct Impl;
1322  std::unique_ptr<Impl> pImpl_;
1323  };
1324 
1326  class RADFile : public RADIODevice {
1327  public:
1331  explicit RADFile(std::string fileName);
1333  ~RADFile() override;
1334 
1336  void setFileName(std::string fileName);
1338  const std::string& fileName() const;
1339 
1341  bool open(OpenMode mode) override;
1343  void close() override;
1345  bool isOpen() const override;
1347  ssize_t readData(void* buffer, size_t maxBytes) override;
1349  ssize_t writeData(const void* data, size_t size) override;
1350 
1352  bool seek(size_t position);
1354  size_t position() const;
1356  size_t size() const;
1357 
1358  private:
1359  struct Impl;
1360  std::unique_ptr<Impl> pImpl_;
1361  };
1362 
1365  public:
1367  explicit RADDataStream(RADIODevice& device);
1368 
1370  void setByteOrder(ByteOrder byteOrder);
1376  bool ok() const;
1378  void resetStatus();
1379 
1381  RADDataStream& operator<<(uint8_t value);
1383  RADDataStream& operator<<(uint16_t value);
1385  RADDataStream& operator<<(uint32_t value);
1387  RADDataStream& operator<<(uint64_t value);
1389  RADDataStream& operator<<(int8_t value);
1391  RADDataStream& operator<<(int16_t value);
1393  RADDataStream& operator<<(int32_t value);
1395  RADDataStream& operator<<(int64_t value);
1397  RADDataStream& operator<<(float value);
1399  RADDataStream& operator<<(double value);
1401  RADDataStream& operator<<(const std::string& value);
1403  RADDataStream& operator<<(const std::vector<uint8_t>& value);
1404 
1406  RADDataStream& operator>>(uint8_t& value);
1408  RADDataStream& operator>>(uint16_t& value);
1410  RADDataStream& operator>>(uint32_t& value);
1412  RADDataStream& operator>>(uint64_t& value);
1414  RADDataStream& operator>>(int8_t& value);
1416  RADDataStream& operator>>(int16_t& value);
1418  RADDataStream& operator>>(int32_t& value);
1420  RADDataStream& operator>>(int64_t& value);
1422  RADDataStream& operator>>(float& value);
1424  RADDataStream& operator>>(double& value);
1426  RADDataStream& operator>>(std::string& value);
1428  RADDataStream& operator>>(std::vector<uint8_t>& value);
1429 
1430  private:
1431  bool writeRaw(const void* data, size_t size);
1432  bool readRaw(void* data, size_t size);
1433  template<typename T>
1434  bool writeIntegral(T value);
1435  template<typename T>
1436  bool readIntegral(T& value);
1437 
1438  RADIODevice& device_;
1439  ByteOrder byteOrder_ = ByteOrder::LittleEndian;
1440  DataStreamStatus status_ = DataStreamStatus::Ok;
1441  };
1442 
1444  enum class FileSystemEvent {
1446  Created,
1448  Modified,
1450  Removed,
1452  Moved,
1454  Overflow,
1456  WatchLost,
1458  Unknown
1459  };
1460 
1463  public:
1464  RADEvents:
1466  RAD_EVENT(changed, (std::string, FileSystemEvent));
1468  RAD_EVENT(errorOccurred, (std::string));
1469 
1474 
1476  bool addPath(const std::string& path);
1478  bool addPath(const std::string& path, bool recursive);
1480  void removePath(const std::string& path);
1482  void clear();
1484  std::vector<std::string> paths() const;
1485 
1486  private:
1487  struct Impl;
1488  std::shared_ptr<Impl> pImpl_;
1489  };
1490 
1492  class RADFuture {
1493  public:
1497  explicit RADFuture(std::shared_ptr<std::shared_future<RADVariant>> future);
1498 
1500  bool isValid() const;
1502  bool isFinished() const;
1504  RADVariant result(RADVariant defaultValue = {}) const;
1506  void wait() const;
1507 
1508  private:
1509  std::shared_ptr<std::shared_future<RADVariant>> future_;
1510  };
1511 
1513  template<typename T>
1514  class RADFutureT {
1515  public:
1517  RADFutureT() = default;
1519  explicit RADFutureT(std::shared_ptr<std::shared_future<T>> future)
1520  : future_(std::move(future)) {}
1521 
1523  bool isValid() const { return future_ && future_->valid(); }
1525  bool isFinished() const {
1526  return isValid() && future_->wait_for(std::chrono::seconds(0)) == std::future_status::ready;
1527  }
1529  void wait() const { if (isValid()) future_->wait(); }
1531  T result() const { return future_->get(); }
1533  T resultOr(T defaultValue) const {
1534  if (!isFinished()) return defaultValue;
1535  try { return future_->get(); } catch (...) { return defaultValue; }
1536  }
1537 
1539  template<typename F>
1540  void then(EventLoop& loop, F&& continuation) const {
1541  auto future = future_;
1542  auto handle = loop.handle();
1543  auto fn = std::make_shared<std::decay_t<F>>(std::forward<F>(continuation));
1544  std::thread([future, handle, fn]() mutable {
1545  if (!future) return;
1546  try {
1547  T value = future->get();
1548  handle.post([fn, value = std::move(value)]() mutable { (*fn)(std::move(value)); });
1549  } catch (...) {
1550  handle.post([fn]() mutable { (*fn)(T{}); });
1551  }
1552  }).detach();
1553  }
1554 
1555  private:
1556  std::shared_ptr<std::shared_future<T>> future_;
1557  };
1558 
1560  template<>
1561  class RADFutureT<void> {
1562  public:
1564  RADFutureT() = default;
1566  explicit RADFutureT(std::shared_ptr<std::shared_future<void>> future)
1567  : future_(std::move(future)) {}
1569  bool isValid() const { return future_ && future_->valid(); }
1571  bool isFinished() const {
1572  return isValid() && future_->wait_for(std::chrono::seconds(0)) == std::future_status::ready;
1573  }
1575  void wait() const { if (isValid()) future_->wait(); }
1577  void result() const { if (future_) future_->get(); }
1579  template<typename F>
1580  void then(EventLoop& loop, F&& continuation) const {
1581  auto future = future_;
1582  auto handle = loop.handle();
1583  auto fn = std::make_shared<std::decay_t<F>>(std::forward<F>(continuation));
1584  std::thread([future, handle, fn]() mutable {
1585  if (future) {
1586  try { future->get(); } catch (...) {}
1587  }
1588  handle.post([fn]() mutable { (*fn)(); });
1589  }).detach();
1590  }
1591 
1592  private:
1593  std::shared_ptr<std::shared_future<void>> future_;
1594  };
1595 
1597  template<typename T>
1598  class RADPromise {
1599  public:
1602  : promise_(std::make_shared<std::promise<T>>()),
1603  future_(std::make_shared<std::shared_future<T>>(promise_->get_future().share())) {}
1605  RADFutureT<T> future() const { return RADFutureT<T>(future_); }
1607  void setValue(T value) { promise_->set_value(std::move(value)); }
1609  void setException(std::exception_ptr error) { promise_->set_exception(error); }
1610 
1611  private:
1612  std::shared_ptr<std::promise<T>> promise_;
1613  std::shared_ptr<std::shared_future<T>> future_;
1614  };
1615 
1617  template<>
1618  class RADPromise<void> {
1619  public:
1622  : promise_(std::make_shared<std::promise<void>>()),
1623  future_(std::make_shared<std::shared_future<void>>(promise_->get_future().share())) {}
1625  RADFutureT<void> future() const { return RADFutureT<void>(future_); }
1627  void setValue() { promise_->set_value(); }
1629  void setException(std::exception_ptr error) { promise_->set_exception(error); }
1630 
1631  private:
1632  std::shared_ptr<std::promise<void>> promise_;
1633  std::shared_ptr<std::shared_future<void>> future_;
1634  };
1635 
1637  class RADThreadPool : public RADObject {
1638  public:
1640  explicit RADThreadPool(size_t threadCount = std::thread::hardware_concurrency());
1642  ~RADThreadPool() override;
1643 
1645  RADFuture submit(EventLoop& completionLoop, std::function<RADVariant()> task);
1647  template<typename F>
1648  auto submitTyped(EventLoop& completionLoop, F&& task) -> RADFutureT<std::invoke_result_t<F>> {
1649  using ReturnType = std::invoke_result_t<F>;
1650  auto promise = std::make_shared<std::promise<ReturnType>>();
1651  auto future = std::make_shared<std::shared_future<ReturnType>>(promise->get_future().share());
1652  auto taskPtr = std::make_shared<std::decay_t<F>>(std::forward<F>(task));
1653  enqueue([promise, taskPtr, &completionLoop]() mutable {
1654  try {
1655  if constexpr (std::is_void_v<ReturnType>) {
1656  (*taskPtr)();
1657  promise->set_value();
1658  } else {
1659  promise->set_value((*taskPtr)());
1660  }
1661  completionLoop.post([] {});
1662  } catch (...) {
1663  promise->set_exception(std::current_exception());
1664  completionLoop.post([] {});
1665  }
1666  });
1667  return RADFutureT<ReturnType>(future);
1668  }
1670  template<typename F>
1671  auto submitCancellable(EventLoop& completionLoop, RADCancellationToken token, F&& task)
1673  using ReturnType = std::invoke_result_t<F, RADCancellationToken>;
1674  auto promise = std::make_shared<std::promise<ReturnType>>();
1675  auto future = std::make_shared<std::shared_future<ReturnType>>(promise->get_future().share());
1676  auto taskPtr = std::make_shared<std::decay_t<F>>(std::forward<F>(task));
1677  enqueue([promise, taskPtr, token, &completionLoop]() mutable {
1678  try {
1679  if constexpr (std::is_void_v<ReturnType>) {
1680  (*taskPtr)(token);
1681  promise->set_value();
1682  } else {
1683  promise->set_value((*taskPtr)(token));
1684  }
1685  completionLoop.post([] {});
1686  } catch (...) {
1687  promise->set_exception(std::current_exception());
1688  completionLoop.post([] {});
1689  }
1690  });
1691  return RADFutureT<ReturnType>(future);
1692  }
1694  void waitForDone();
1696  size_t threadCount() const;
1697 
1698  private:
1699  void enqueue(std::function<void()> task);
1700  struct Impl;
1701  std::shared_ptr<Impl> pImpl_;
1702  };
1703 
1706  public:
1707  RADEvents:
1709  RAD_EVENT(modelReset, ());
1711  RAD_EVENT(dataChanged, (size_t, size_t));
1713  RAD_EVENT(rowsInserted, (size_t, size_t));
1715  RAD_EVENT(rowsRemoved, (size_t, size_t));
1716 
1718  virtual ~RADAbstractItemModel() = default;
1720  virtual size_t rowCount() const = 0;
1722  virtual size_t columnCount() const = 0;
1724  virtual RADVariant data(size_t row, size_t column = 0) const = 0;
1725  };
1726 
1729  public:
1731  size_t rowCount() const override;
1733  size_t columnCount() const override;
1735  RADVariant data(size_t row, size_t column = 0) const override;
1736 
1738  void append(std::string value);
1740  void set(size_t row, std::string value);
1742  void remove(size_t row);
1744  void clear();
1746  const std::vector<std::string>& values() const;
1747 
1748  private:
1749  std::vector<std::string> values_;
1750  };
1751 
1753  class RADProcess : public RADObject {
1754  public:
1755  RADEvents:
1757  RAD_EVENT(started, ());
1759  RAD_EVENT(finished, (int));
1761  RAD_EVENT(errorOccurred, (std::string));
1762 
1766  ~RADProcess() override;
1767 
1769  bool start(const std::string& program, const std::vector<std::string>& arguments = {});
1771  bool waitForFinished(int timeoutMs = -1);
1773  void kill();
1774 
1778  int exitCode() const;
1780  std::string readAllStandardOutput() const;
1782  std::string readAllStandardError() const;
1783 
1784  private:
1785  struct Impl;
1786  std::unique_ptr<Impl> pImpl_;
1787  };
1788 
1790  class RADPtyProcess : public RADObject {
1791  public:
1792  RADEvents:
1794  RAD_EVENT(started, ());
1796  RAD_EVENT(finished, (int));
1798  RAD_EVENT(errorOccurred, (std::string));
1799 
1803  ~RADPtyProcess() override;
1804 
1806  bool start(const std::string& program = {}, const std::vector<std::string>& arguments = {},
1807  uint16_t rows = 30, uint16_t columns = 120);
1809  bool waitForFinished(int timeoutMs = -1);
1811  void kill();
1813  void close();
1814 
1816  ssize_t readData(void* buffer, size_t maxBytes);
1818  ssize_t writeData(const void* data, size_t size);
1820  ssize_t write(const std::string& text);
1822  bool resizeTerminal(uint16_t rows, uint16_t columns);
1823 
1827  int exitCode() const;
1828 
1829  private:
1830  struct Impl;
1831  std::unique_ptr<Impl> pImpl_;
1832  };
1833 
1835  class Timer : public RADObject {
1836  public:
1837  RADEvents:
1839  RAD_EVENT(timeout, ());
1841  RAD_EVENT(errorOccurred, (std::string));
1842 
1847 
1849  void start(int intervalMs, EventLoop& targetLoop);
1851  void start(EventLoop& targetLoop);
1853  void stop();
1855  void setInterval(int intervalMs);
1857  int interval() const;
1859  bool isActive() const;
1860 
1862  static void singleShot(int intervalMs, EventLoop& targetLoop, EventLoop::Task task);
1863 
1864  private:
1865  std::atomic<bool> active_;
1866  std::thread timerThread_;
1867  std::atomic<int> timerFd_{-1};
1868  std::atomic<int> stopFd_{-1};
1869  std::atomic<int> intervalMs_{0};
1870  };
1871 
1873  class RADThread : public RADObject {
1874  public:
1875  RADEvents:
1877  RAD_EVENT(started, ());
1879  RAD_EVENT(finished, ());
1880 
1881  public:
1885  virtual ~RADThread();
1886 
1890  void quit();
1892  void wait();
1896  bool isRunning() const;
1897  protected:
1899  virtual void run();
1900  private:
1901  struct Impl;
1902  std::unique_ptr<Impl> pImpl;
1903  };
1904 
1905  namespace Internal {
1906  template<typename... Args>
1907  struct EventBinder {Event<void(Args...)>& targetEvent;
1908  EventBinder(Event<void(Args...)>& ev) : targetEvent(ev) {}
1909  void operator()(Args... args) {
1910  targetEvent.raise(std::forward(args)...);
1911  }
1912  };
1913  struct TriggerHelper {
1914  void operator<<(Event<void()>& targetEvent) { targetEvent.raise(); }
1915  template<typename... Args>EventBinder<Args...> operator<<(Event<void(Args...)>& targetEvent) {
1916  return EventBinder<Args...>(targetEvent);
1917  }
1918  };
1919  }
1920 
1922  enum class LogLevel { INFO, DEBUG };
1923 
1925  void initLogger();
1928 
1929  namespace Internal {
1931  class LogStream {
1932  public:
1936  ~LogStream(); // Flushes the accumulated string buffer to the background thread on destruction
1937 
1939  template<typename T>
1940  LogStream& operator<<(const T& value) {
1941  stream_ << value;
1942  return *this;
1943  }
1944 
1946  LogStream& operator<<(std::ostream& (*manip)(std::ostream&)) {
1947  stream_ << manip;
1948  return *this;
1949  }
1950 
1951  private:
1952  LogLevel level_;
1953  std::stringstream stream_;
1954  };
1955  }
1956 } // namespace RADCore
1957 #endif
#define RAD_EVENT(Name, Signature)
Declares a typed RADCore event; example: RAD_EVENT(done, (int)).
Definition: RADCore.h:65
#define RADEvents
Marks a public event declaration block in RADObject-derived classes.
Definition: RADCore.h:43
Explicit event connection handle.
Definition: RADCore.h:903
void disconnect()
Disconnects the associated event handler once.
Connection()=default
Creates a disconnected handle.
bool isConnected() const
Returns true while the connection is still active.
Low-level raw handler collection used internally by typed Event.
Definition: RADCore.h:1075
void addRawHandler(size_t id, RawTask task)
Adds a raw handler by id.
void removeRawHandler(size_t id)
Removes a raw handler by id.
void invokeAll()
Invokes all raw handlers.
std::function< void()> RawTask
Raw no-argument task type.
Definition: RADCore.h:1078
Weak posting handle for EventLoop tasks that may outlive the loop object.
Definition: RADCore.h:1007
bool post(EventLoop::Task task) const
Posts normal-priority task; returns false when the loop is gone.
EventLoopHandle()=default
Creates an invalid handle.
bool isValid() const
Returns true when the referenced loop still accepts work.
bool post(Priority priority, EventLoop::Task task) const
Posts task with explicit priority; returns false when the loop is gone.
bool postDelayed(int delayMs, EventLoop::Task task) const
Posts task after delayMs milliseconds; returns false when the loop is gone.
RADCore task event loop with locked and low-latency scheduling strategies.
Definition: RADCore.h:956
EventLoop(LoopStrategy strategy=RADEVENT_LOCK)
Creates an event loop using strategy.
void post(Priority priority, Task task)
Posts task with explicit priority.
bool processEvents()
Processes currently queued events without entering the main loop.
void post(F &&f, Args &&... args)
Binds f and args into a normal-priority task.
Definition: RADCore.h:993
bool postDelayed(int delayMs, Task task)
Posts task to this loop after delayMs milliseconds; returns false when stopped.
EventLoopHandle handle() const
Returns a weak posting handle safe to keep beyond this EventLoop object.
void post(Task task)
Posts task at normal priority.
void exec()
Runs the event loop until quit() is called.
~EventLoop()
Stops and destroys the loop implementation.
bool isEventThread() const
Returns true when called from the thread running exec().
void post(Priority priority, F &&f, Args &&... args)
Binds f and args into a task posted with priority.
Definition: RADCore.h:984
std::function< void()> Task
Task callable type.
Definition: RADCore.h:959
void quit()
Requests the event loop to exit.
void disconnect(size_t targetId)
Disconnects a handler by event-local id.
Definition: RADCore.h:1216
Connection connect_queued(EventLoop &loop, T *receiver, void(T::*memberFunc)(Args...))
Connects this event to a receiver member function through loop.
Definition: RADCore.h:1177
Event()
Creates an empty event.
Definition: RADCore.h:1107
Connection connect(T *receiver, void(T::*memberFunc)(Args...))
Connects this event to a RADObject receiver member function.
Definition: RADCore.h:1123
~Event()
Marks the event dead and disconnects handlers.
Definition: RADCore.h:1110
Typed event template; use RAD_EVENT to declare instances.
Definition: RADCore.h:874
Streaming log proxy used by RADInfo() and RADDebug().
Definition: RADCore.h:1931
LogStream & operator<<(const T &value)
Appends value to the log stream.
Definition: RADCore.h:1940
LogStream(LogLevel level)
Creates a log stream for level.
~LogStream()
Flushes the accumulated string to the logger.
LogStream & operator<<(std::ostream &(*manip)(std::ostream &))
Appends an ostream manipulator such as std::endl.
Definition: RADCore.h:1946
Minimal abstract item model for UI/model integrations.
Definition: RADCore.h:1705
virtual ~RADAbstractItemModel()=default
Destroys model implementations through the base class.
virtual size_t columnCount() const =0
Returns column count.
virtual size_t rowCount() const =0
Returns row count.
virtual RADVariant data(size_t row, size_t column=0) const =0
Returns data at row/column.
In-memory RADIODevice backed by a byte vector.
Definition: RADCore.h:1289
ssize_t readData(void *buffer, size_t maxBytes) override
Reads raw bytes from the current position.
ssize_t writeData(const void *data, size_t size) override
Writes raw bytes at the current position.
void close() override
Closes the memory buffer.
bool seek(size_t position)
Moves the current read/write position.
RADBuffer(std::vector< uint8_t > data)
Creates a buffer initialized with data.
size_t size() const
Returns current buffer size in bytes.
void clear()
Clears buffer contents and resets position.
RADBuffer()
Creates an empty buffer.
bool isOpen() const override
Returns true when open.
size_t position() const
Returns current read/write position.
~RADBuffer() override
Destroys the buffer.
const std::vector< uint8_t > & data() const
Returns the underlying byte vector.
bool open(OpenMode mode) override
Opens the memory buffer.
Owner object used to request cancellation on associated tokens.
Definition: RADCore.h:277
void cancel()
Requests cancellation.
Definition: RADCore.h:284
bool isCancellationRequested() const
Returns true when cancellation was requested.
Definition: RADCore.h:286
RADCancellationSource()
Creates a source with a fresh token.
Definition: RADCore.h:280
RADCancellationToken token() const
Returns the token that observers should poll.
Definition: RADCore.h:282
Shared cancellation token passed to long-running tasks.
Definition: RADCore.h:260
RADCancellationToken()
Creates a non-cancelled standalone token.
Definition: RADCore.h:263
bool isCancellationRequested() const
Returns true when cancellation has been requested.
Definition: RADCore.h:265
Binary serialization stream for RADIODevice.
Definition: RADCore.h:1364
RADDataStream & operator>>(uint16_t &value)
Reads an unsigned 16-bit integer.
RADDataStream(RADIODevice &device)
Creates a stream over device.
void resetStatus()
Resets status to Ok.
RADDataStream & operator<<(const std::string &value)
Writes a length-prefixed string.
RADDataStream & operator<<(uint64_t value)
Writes an unsigned 64-bit integer.
RADDataStream & operator>>(int32_t &value)
Reads a signed 32-bit integer.
DataStreamStatus status() const
Returns current stream status.
RADDataStream & operator<<(int32_t value)
Writes a signed 32-bit integer.
RADDataStream & operator>>(std::vector< uint8_t > &value)
Reads a length-prefixed byte array.
RADDataStream & operator<<(uint16_t value)
Writes an unsigned 16-bit integer.
RADDataStream & operator<<(double value)
Writes a 64-bit double.
RADDataStream & operator<<(uint32_t value)
Writes an unsigned 32-bit integer.
RADDataStream & operator>>(int16_t &value)
Reads a signed 16-bit integer.
void setByteOrder(ByteOrder byteOrder)
Sets byte order for integer and floating point values.
RADDataStream & operator>>(uint8_t &value)
Reads an unsigned 8-bit integer.
RADDataStream & operator<<(int16_t value)
Writes a signed 16-bit integer.
bool ok() const
Returns true when status is Ok.
RADDataStream & operator>>(float &value)
Reads a 32-bit float.
RADDataStream & operator>>(int8_t &value)
Reads a signed 8-bit integer.
RADDataStream & operator<<(const std::vector< uint8_t > &value)
Writes a length-prefixed byte array.
RADDataStream & operator<<(uint8_t value)
Writes an unsigned 8-bit integer.
RADDataStream & operator>>(uint64_t &value)
Reads an unsigned 64-bit integer.
RADDataStream & operator>>(double &value)
Reads a 64-bit double.
RADDataStream & operator<<(int8_t value)
Writes a signed 8-bit integer.
RADDataStream & operator>>(uint32_t &value)
Reads an unsigned 32-bit integer.
RADDataStream & operator<<(float value)
Writes a 32-bit float.
RADDataStream & operator<<(int64_t value)
Writes a signed 64-bit integer.
ByteOrder byteOrder() const
Returns current byte order.
RADDataStream & operator>>(int64_t &value)
Reads a signed 64-bit integer.
RADDataStream & operator>>(std::string &value)
Reads a length-prefixed string.
UTC millisecond timestamp helper.
Definition: RADCore.h:404
static std::optional< RADDateTime > fromIsoString(const std::string &isoString)
Parses an ISO-like UTC string.
int64_t toUnixMilliseconds() const
Returns Unix milliseconds.
bool isValid() const
Returns true when this object contains a valid timestamp.
RADDateTime(int64_t unixMilliseconds)
Creates a valid UTC date-time from Unix milliseconds.
RADDateTime()
Creates an invalid date-time.
static RADDateTime fromUnixMilliseconds(int64_t unixMilliseconds)
Creates a date-time from Unix milliseconds.
static RADDateTime nowUtc()
Returns current UTC time.
std::string toIsoString() const
Formats as an ISO-like UTC string.
Deadline helper for timeout loops and cancellation-aware waits.
Definition: RADCore.h:234
RADDeadlineTimer(int64_t intervalMs)
Creates a deadline intervalMs in the future.
Definition: RADCore.h:239
bool isValid() const
Returns true when this deadline has been configured.
Definition: RADCore.h:243
bool hasExpired() const
Returns true when the deadline has passed.
Definition: RADCore.h:245
int64_t remainingMilliseconds() const
Returns milliseconds remaining, or 0 when expired/invalid.
Definition: RADCore.h:247
RADDeadlineTimer()=default
Creates an expired deadline.
Monotonic elapsed timer based on std::chrono::steady_clock.
Definition: RADCore.h:211
double elapsedSeconds() const
Returns elapsed seconds as a double.
Definition: RADCore.h:227
void restart()
Restarts the timer.
Definition: RADCore.h:216
RADElapsedTimer()
Creates and starts the timer.
Definition: RADCore.h:214
int64_t elapsedMicroseconds() const
Returns elapsed microseconds.
Definition: RADCore.h:223
int64_t elapsedNanoseconds() const
Returns elapsed nanoseconds.
Definition: RADCore.h:218
int64_t elapsedMilliseconds() const
Returns elapsed milliseconds.
Definition: RADCore.h:225
Structured error object returned by RADResult and newer APIs.
Definition: RADCore.h:104
int code() const
Returns numeric error code; 0 means no error.
Definition: RADCore.h:115
RADError(int code, std::string message)
Creates an error with code and message.
Definition: RADCore.h:109
bool hasError() const
Returns true when this object represents an error.
Definition: RADCore.h:113
RADError()=default
Creates a no-error object.
const std::string & message() const
Returns human-readable error message.
Definition: RADCore.h:117
inotify-backed filesystem watcher that emits on a RADCore EventLoop.
Definition: RADCore.h:1462
void removePath(const std::string &path)
Removes a watched path.
~RADFileSystemWatcher() override
Stops the watcher.
std::vector< std::string > paths() const
Returns currently watched paths.
RADFileSystemWatcher(EventLoop &loop)
Creates a watcher that posts events to loop.
bool addPath(const std::string &path)
Adds a non-recursive path watch.
bool addPath(const std::string &path, bool recursive)
Adds a path watch, recursively when requested.
void clear()
Removes all watched paths.
File-backed RADIODevice.
Definition: RADCore.h:1326
void setFileName(std::string fileName)
Sets the file path.
bool isOpen() const override
Returns true when the file is open.
ssize_t readData(void *buffer, size_t maxBytes) override
Reads raw bytes from the file.
size_t position() const
Returns current byte position.
void close() override
Closes the file descriptor.
~RADFile() override
Closes the file if needed.
bool seek(size_t position)
Seeks to an absolute byte position.
const std::string & fileName() const
Returns the file path.
bool open(OpenMode mode) override
Opens the file with mode.
size_t size() const
Returns file size in bytes.
ssize_t writeData(const void *data, size_t size) override
Writes raw bytes to the file.
RADFile(std::string fileName)
Creates a file bound to fileName.
RADFile()
Creates a file with no path.
Void typed future specialization.
Definition: RADCore.h:1561
void wait() const
Blocks until the result is ready.
Definition: RADCore.h:1575
void then(EventLoop &loop, F &&continuation) const
Posts continuation to loop after this future completes.
Definition: RADCore.h:1580
RADFutureT()=default
Creates an invalid future.
void result() const
Waits and rethrows any task exception.
Definition: RADCore.h:1577
bool isFinished() const
Returns true when the result is ready.
Definition: RADCore.h:1571
bool isValid() const
Returns true when a future is present.
Definition: RADCore.h:1569
RADFutureT(std::shared_ptr< std::shared_future< void >> future)
Wraps an existing shared future.
Definition: RADCore.h:1566
Typed shared future with optional continuation support.
Definition: RADCore.h:1514
bool isFinished() const
Returns true when the result is ready.
Definition: RADCore.h:1525
RADFutureT()=default
Creates an invalid future.
T resultOr(T defaultValue) const
Returns result or defaultValue if not ready or failed.
Definition: RADCore.h:1533
void wait() const
Blocks until the result is ready.
Definition: RADCore.h:1529
void then(EventLoop &loop, F &&continuation) const
Posts continuation to loop after this future completes.
Definition: RADCore.h:1540
T result() const
Returns the result, rethrowing any task exception.
Definition: RADCore.h:1531
bool isValid() const
Returns true when a future is present.
Definition: RADCore.h:1523
RADFutureT(std::shared_ptr< std::shared_future< T >> future)
Wraps an existing shared future.
Definition: RADCore.h:1519
Shared future wrapper returning RADVariant results.
Definition: RADCore.h:1492
bool isFinished() const
Returns true when the result is ready.
RADVariant result(RADVariant defaultValue={}) const
Returns result or defaultValue if not ready or failed.
bool isValid() const
Returns true when a future is present.
RADFuture()
Creates an invalid future.
RADFuture(std::shared_ptr< std::shared_future< RADVariant >> future)
Wraps an existing shared future.
void wait() const
Blocks until the future is ready.
Abstract byte-oriented IO device similar to QIODevice.
Definition: RADCore.h:1254
virtual bool open(OpenMode mode)=0
Opens the device with mode.
virtual ~RADIODevice()=default
Destroys the IO device.
ssize_t write(const std::string &text)
Writes string bytes.
virtual void close()=0
Closes the device.
std::vector< uint8_t > read(size_t maxBytes)
Reads up to maxBytes into a byte vector.
std::vector< uint8_t > readAll(size_t chunkSize=8192)
Reads all available data in chunks.
ssize_t write(const std::vector< uint8_t > &data)
Writes a byte vector.
virtual bool isOpen() const =0
Returns true when open.
virtual ssize_t writeData(const void *data, size_t size)=0
Writes raw bytes from data.
virtual ssize_t readData(void *buffer, size_t maxBytes)=0
Reads raw bytes into buffer.
JSON document wrapper around a root RADJsonValue.
Definition: RADCore.h:616
RADJsonValue & root()
Returns mutable root value.
const RADJsonValue & root() const
Returns const root value.
RADJsonDocument()
Creates a document with null root.
RADJsonDocument(RADJsonValue root)
Creates a document from root.
static std::optional< RADJsonDocument > fromFile(const std::string &path, std::string *error=nullptr)
Loads and parses JSON from path.
std::string toJson(bool pretty=false) const
Serializes root to JSON.
static std::optional< RADJsonDocument > fromJson(const std::string &json, std::string *error=nullptr)
Parses JSON text.
bool toFile(const std::string &path, bool pretty=true, std::string *error=nullptr) const
Writes JSON to path.
JSON value supporting null, bool, number, string, array, and object.
Definition: RADCore.h:509
bool isNull() const
Returns true when value is null.
bool isArray() const
Returns true when value is array.
RADJsonValue & operator[](const std::string &key)
Returns object member by key, creating it if needed.
RADJsonValue(RADJsonValue &&other) noexcept=default
Moves the value without deep-copying.
RADJsonValue & operator=(RADJsonValue &&other) noexcept=default
Moves the value without deep-copying.
size_t size() const
Returns array length or object member count.
void append(RADJsonValue value)
Appends value to an array, converting to array if needed.
RADJsonValue(int value)
Creates a JSON number from int.
RADJsonValue(const RADJsonValue &other)
Deep-copies arrays and objects so mutations do not alias the source.
bool toBool(bool defaultValue=false) const
Converts to bool or returns defaultValue.
double toNumber(double defaultValue=0.0) const
Converts to double or returns defaultValue.
void remove(const std::string &key)
Removes key from an object.
RADJsonValue & operator[](size_t index)
Returns array element by index, expanding when needed.
int toInt(int defaultValue=0) const
Converts to int or returns defaultValue.
bool isBool() const
Returns true when value is bool.
bool isObject() const
Returns true when value is object.
std::string toString(const std::string &defaultValue={}) const
Converts to string or returns defaultValue.
RADJsonValue & operator=(const RADJsonValue &other)
Deep-copies arrays and objects so mutations do not alias the source.
std::string toJson(bool pretty=false, int indent=0) const
Serializes this value to JSON.
RADJsonValue(const char *value)
Creates a JSON string from C string.
bool isNumber() const
Returns true when value is number.
JsonType type() const
Returns current JSON type.
RADJsonValue(bool value)
Creates a JSON bool.
RADJsonValue(std::string value)
Creates a JSON string.
const RADJsonValue & operator[](size_t index) const
Returns array element by index or null value when missing.
std::vector< std::string > keys() const
Returns object keys.
RADJsonValue(std::nullptr_t)
Creates JSON null.
const RADJsonValue & operator[](const std::string &key) const
Returns object member by key or null value when missing.
RADJsonValue(int64_t value)
Creates a JSON number from int64.
bool isString() const
Returns true when value is string.
int64_t toInt64(int64_t defaultValue=0) const
Converts to int64 or returns defaultValue.
bool contains(const std::string &key) const
Returns true when object contains key.
static RADJsonValue array()
Creates an empty JSON array.
RADJsonValue()
Creates JSON null.
RADJsonValue(double value)
Creates a JSON number from double.
static RADJsonValue object()
Creates an empty JSON object.
Advisory filesystem lock file.
Definition: RADCore.h:827
void unlock()
Releases the lock if held.
RADLockFile(std::string fileName)
Creates a lock file object for fileName.
bool tryLock()
Attempts to acquire the lock.
const std::string & fileName() const
Returns the lock file path.
bool isLocked() const
Returns true when this object holds the lock.
RADLockFile(const RADLockFile &)=delete
Lock files cannot be copied.
~RADLockFile()
Unlocks on destruction when needed.
RADLockFile & operator=(const RADLockFile &)=delete
Lock files cannot be copied.
Base class for event receivers, senders, and thread-affinity aware objects.
Definition: RADCore.h:931
EventLoop * associatedEventLoop() const
Returns the associated event loop, if any.
void moveToThread(std::thread::id tId, EventLoop *loop=nullptr)
Moves the object's affinity to tId and optional loop.
virtual ~RADObject()
Disconnects tracked event links and releases lifetime token.
ThreadAffinity threadAffinity() const
Returns both thread id and associated loop atomically.
RADObject()
Creates a RADObject bound to the current thread.
std::thread::id threadId() const
Returns the thread id this object is currently associated with.
std::weak_ptr< void > lifetimeToken() const
Returns a weak token used to drop queued callbacks after destruction.
void registerLink(const ConnectionRecord &record)
Registers a connection for cleanup when this object is destroyed.
Child process helper for stdout/stderr capture.
Definition: RADCore.h:1753
bool waitForFinished(int timeoutMs=-1)
Waits for process exit; timeoutMs < 0 waits indefinitely.
void kill()
Sends a kill request to the process.
RADProcess()
Creates a non-running process.
std::string readAllStandardError() const
Returns captured stderr.
ProcessState state() const
Returns process state.
bool start(const std::string &program, const std::vector< std::string > &arguments={})
Starts program with arguments.
int exitCode() const
Returns exit code after finish.
~RADProcess() override
Kills or cleans up the process if needed.
std::string readAllStandardOutput() const
Returns captured stdout.
RADFutureT< void > future() const
Returns the associated typed future.
Definition: RADCore.h:1625
void setException(std::exception_ptr error)
Sets an exception result.
Definition: RADCore.h:1629
RADPromise()
Creates a promise/future pair.
Definition: RADCore.h:1621
void setValue()
Sets successful completion.
Definition: RADCore.h:1627
Typed promise that creates RADFutureT.
Definition: RADCore.h:1598
RADFutureT< T > future() const
Returns the associated typed future.
Definition: RADCore.h:1605
void setValue(T value)
Sets the result value.
Definition: RADCore.h:1607
RADPromise()
Creates a promise/future pair.
Definition: RADCore.h:1601
void setException(std::exception_ptr error)
Sets an exception result.
Definition: RADCore.h:1609
PTY-backed process helper for terminal applications.
Definition: RADCore.h:1790
void close()
Closes the PTY handle.
RADPtyProcess()
Creates a non-running PTY process.
bool waitForFinished(int timeoutMs=-1)
Waits for process exit; timeoutMs < 0 waits indefinitely.
~RADPtyProcess() override
Stops and cleans up the PTY process if needed.
ssize_t write(const std::string &text)
Writes string bytes to the PTY.
ProcessState state() const
Returns process state.
bool resizeTerminal(uint16_t rows, uint16_t columns)
Resizes the PTY terminal dimensions.
void kill()
Sends a kill request to the child.
ssize_t readData(void *buffer, size_t maxBytes)
Reads bytes from the PTY.
int exitCode() const
Returns exit code after finish.
ssize_t writeData(const void *data, size_t size)
Writes bytes to the PTY.
bool start(const std::string &program={}, const std::vector< std::string > &arguments={}, uint16_t rows=30, uint16_t columns=120)
Starts program in a PTY; empty program selects the user's shell.
bool hasError() const
Returns true when this result has an error.
Definition: RADCore.h:165
bool ok() const
Returns true when no error is present.
Definition: RADCore.h:163
static RADResult failure(RADError error)
Creates a failed result.
Definition: RADCore.h:161
const RADError & error() const
Returns the error object.
Definition: RADCore.h:167
static RADResult success()
Creates a successful result.
Definition: RADCore.h:159
Success-or-error return value for APIs that should not throw.
Definition: RADCore.h:126
const T & value() const
Returns the result value; callers should check ok().
Definition: RADCore.h:140
T valueOr(T defaultValue) const
Returns value or defaultValue when failed.
Definition: RADCore.h:144
static RADResult success(T value)
Creates a successful result.
Definition: RADCore.h:129
T & value()
Returns the result value; callers should check ok().
Definition: RADCore.h:138
const RADError & error() const
Returns the error object.
Definition: RADCore.h:142
static RADResult failure(RADError error)
Creates a failed result.
Definition: RADCore.h:131
bool hasError() const
Returns true when this result has an error.
Definition: RADCore.h:136
bool ok() const
Returns true when a value is present.
Definition: RADCore.h:134
void setValue(const std::string &key, RADJsonValue value)
Sets value for key.
RADSettings(std::string fileName)
Creates settings bound to fileName.
void clear()
Removes all settings.
const std::string & fileName() const
Returns backing file path.
bool save(std::string *error=nullptr) const
Saves settings to disk.
void remove(const std::string &key)
Removes key.
bool contains(const std::string &key) const
Returns true when key exists.
RADJsonValue value(const std::string &key, RADJsonValue defaultValue={}) const
Returns value for key or defaultValue.
bool load(std::string *error=nullptr)
Loads settings from disk.
Non-owning contiguous view over T values.
Definition: RADCore.h:177
RADSpan()=default
Creates an empty span.
T * end() const
Returns pointer one past last element.
Definition: RADCore.h:198
T * begin() const
Returns pointer to first element.
Definition: RADCore.h:196
T * data() const
Returns mutable pointer to first element.
Definition: RADCore.h:188
RADSpan(T *data, size_t size)
Creates a span over pointer and element count.
Definition: RADCore.h:182
RADSpan(Container &container)
Creates a span over a std::vector-compatible container.
Definition: RADCore.h:185
bool empty() const
Returns true when the span is empty.
Definition: RADCore.h:192
size_t size() const
Returns element count.
Definition: RADCore.h:190
T & operator[](size_t index) const
Returns element at index without bounds checking.
Definition: RADCore.h:194
One-column string list implementation of RADAbstractItemModel.
Definition: RADCore.h:1728
void append(std::string value)
Appends a value.
void set(size_t row, std::string value)
Sets a row value.
size_t rowCount() const override
Returns number of strings.
const std::vector< std::string > & values() const
Returns underlying values.
void remove(size_t row)
Removes a row.
void clear()
Clears all values.
size_t columnCount() const override
Returns 1.
RADVariant data(size_t row, size_t column=0) const override
Returns row string as RADVariant.
RAII temporary directory with optional auto-remove.
Definition: RADCore.h:758
RADTemporaryDirectory(const RADTemporaryDirectory &)=delete
Temporary directories own a filesystem path and cannot be copied.
RADTemporaryDirectory & operator=(const RADTemporaryDirectory &)=delete
Temporary directories own a filesystem path and cannot be copied.
RADTemporaryDirectory(std::string prefix="radlib")
Creates a temporary directory with prefix.
bool isValid() const
Returns true when directory creation succeeded.
RADTemporaryDirectory & operator=(RADTemporaryDirectory &&other) noexcept
Moves ownership from other.
bool autoRemove() const
Returns true when destruction removes the directory.
void setAutoRemove(bool enabled)
Enables or disables removal on destruction.
const std::string & path() const
Returns the temporary directory path.
RADTemporaryDirectory(RADTemporaryDirectory &&other) noexcept
Moves ownership from other.
bool remove()
Removes the directory immediately.
~RADTemporaryDirectory()
Removes the directory when autoRemove is enabled.
RAII temporary file with optional auto-remove.
Definition: RADCore.h:791
bool remove()
Removes the temporary file immediately.
RADTemporaryFile & operator=(const RADTemporaryFile &)=delete
Temporary files own a file descriptor and cannot be copied.
int fd() const
Returns the native file descriptor.
RADTemporaryFile(const RADTemporaryFile &)=delete
Temporary files own a file descriptor and cannot be copied.
RADTemporaryFile & operator=(RADTemporaryFile &&other) noexcept
Moves ownership from other.
RADTemporaryFile(RADTemporaryFile &&other) noexcept
Moves ownership from other.
bool isValid() const
Returns true when file creation succeeded.
const std::string & fileName() const
Returns the temporary file path.
RADTemporaryFile(std::string prefix="radlib")
Creates a temporary file with prefix.
void setAutoRemove(bool enabled)
Enables or disables removal on destruction.
~RADTemporaryFile()
Closes and removes the file when autoRemove is enabled.
bool autoRemove() const
Returns true when destruction removes the file.
Simple worker thread pool that reports completion through RADFuture.
Definition: RADCore.h:1637
auto submitTyped(EventLoop &completionLoop, F &&task) -> RADFutureT< std::invoke_result_t< F >>
Submits a typed task and posts completion wakeup to completionLoop.
Definition: RADCore.h:1648
RADFuture submit(EventLoop &completionLoop, std::function< RADVariant()> task)
Submits task and posts completion wakeup to completionLoop.
auto submitCancellable(EventLoop &completionLoop, RADCancellationToken token, F &&task) -> RADFutureT< std::invoke_result_t< F, RADCancellationToken >>
Submits a typed task that receives a cancellation token.
Definition: RADCore.h:1671
void waitForDone()
Blocks until queued and active tasks are complete.
size_t threadCount() const
Returns number of worker threads.
~RADThreadPool() override
Stops workers after queued tasks complete.
RADThreadPool(size_t threadCount=std::thread::hardware_concurrency())
Creates a pool with threadCount workers.
Thread object with an owned RADCore EventLoop.
Definition: RADCore.h:1873
void quit()
Requests the event loop to quit.
RADThread()
Creates a stopped thread object.
virtual void run()
Override to run custom work before/around the event loop.
bool isRunning() const
Returns true while the thread is running.
void wait()
Blocks until the thread exits.
void start(LoopStrategy strategy=LoopStrategy::RADEVENT_LOCK)
Starts the thread and its event loop.
virtual ~RADThread()
Quits and joins the thread when needed.
EventLoop & eventLoop()
Returns the thread's event loop after start().
Lightweight URL parser for scheme, host, port, path, query, and fragment.
Definition: RADCore.h:455
std::string toString() const
Rebuilds the URL string.
const std::string & query() const
Returns query without '?'.
RADUrl()=default
Creates an invalid empty URL.
const std::string & host() const
Returns host name or address.
uint16_t port(uint16_t defaultPort=0) const
Returns explicit port or defaultPort.
RADUrl(std::string url)
Parses url into a RADUrl.
bool isValid() const
Returns true when parsing succeeded.
static std::optional< RADUrl > parse(const std::string &url)
Parses url and returns nullopt on failure.
const std::string & fragment() const
Returns fragment without '#'.
const std::string & path() const
Returns URL path.
const std::string & scheme() const
Returns URL scheme without colon.
128-bit UUID helper.
Definition: RADCore.h:431
static std::optional< RADUuid > fromString(const std::string &text)
Parses canonical UUID text.
RADUuid(std::array< uint8_t, 16 > bytes)
Creates a UUID from raw bytes.
static RADUuid createUuid()
Creates a random UUID.
RADUuid()
Creates a null UUID.
const std::array< uint8_t, 16 > & bytes() const
Returns raw UUID bytes.
std::string toString() const
Formats as canonical UUID text.
bool isNull() const
Returns true when all UUID bytes are zero.
Small value container used by models, futures, settings, and database rows.
Definition: RADCore.h:364
VariantType type() const
Returns the current variant type.
double toDouble(double defaultValue=0.0) const
Converts to double or returns defaultValue.
RADVariant(int64_t value)
Stores a signed 64-bit integer.
bool isValid() const
Returns true when the variant stores a non-invalid value.
int64_t toInt64(int64_t defaultValue=0) const
Converts to int64 or returns defaultValue.
bool toBool(bool defaultValue=false) const
Converts to bool or returns defaultValue.
RADVariant()
Creates an invalid variant.
RADVariant(bool value)
Stores a boolean.
RADVariant(const char *value)
Stores a C string as std::string.
RADVariant(double value)
Stores a double.
RADVariant(std::string value)
Stores a string.
std::vector< uint8_t > toByteArray() const
Converts to a byte array where supported.
std::string toString(const std::string &defaultValue={}) const
Converts to string or returns defaultValue.
RADVariant(std::vector< uint8_t > value)
Stores a byte array.
RADVariant(int value)
Stores an integer as Int64.
High-precision timer that emits timeout through a RADCore EventLoop.
Definition: RADCore.h:1835
void start(int intervalMs, EventLoop &targetLoop)
Starts the timer with intervalMs and posts timeout to targetLoop.
void setInterval(int intervalMs)
Sets timer interval in milliseconds.
static void singleShot(int intervalMs, EventLoop &targetLoop, EventLoop::Task task)
Posts task once after intervalMs milliseconds.
bool isActive() const
Returns true while the timer is active.
void stop()
Stops the timer.
int interval() const
Returns timer interval in milliseconds.
~Timer()
Stops the timer if active.
Timer()
Creates an inactive timer.
void start(EventLoop &targetLoop)
Starts the timer using the previously configured interval.
bool isDirectory(const std::string &path)
Returns true when path is a directory.
std::optional< std::string > readTextFile(const std::string &path)
Reads a UTF-8/text file into a string.
std::string extension(const std::string &path)
Returns extension component of path.
StandardPath
Standard platform path categories.
Definition: RADCore.h:672
@ Current
Current working directory.
@ Executable
Running executable path.
@ Home
User home directory.
@ Temp
Temporary directory.
@ Downloads
Downloads directory.
@ Documents
Documents directory.
@ Data
Application data directory.
@ Config
Configuration directory.
DirectoryEntryType
Directory entry type.
Definition: RADCore.h:696
@ Unknown
Type could not be determined.
bool remove(const std::string &path)
Removes file or directory path.
std::string tempDirectoryPath()
Returns system temporary directory.
bool createDirectories(const std::string &path)
Creates path and missing parents.
bool exists(const std::string &path)
Returns true when path exists.
std::vector< DirectoryEntry > listEntries(const std::string &path, bool recursive=false)
Lists directory entries, recursively when requested.
bool copyFile(const std::string &source, const std::string &destination, bool overwrite=true)
Copies a file from source to destination.
std::string mimeTypeForFile(const std::string &path)
Guesses MIME type from file contents or extension.
std::string fileName(const std::string &path)
Returns filename component of path.
std::vector< std::string > listDirectory(const std::string &path)
Lists child paths in a directory.
std::string currentPath()
Returns current working directory.
std::string parentPath(const std::string &path)
Returns parent directory path.
bool writeTextFile(const std::string &path, const std::string &text)
Writes text to a file.
std::string standardPath(StandardPath path)
Returns a standard platform path.
bool isFile(const std::string &path)
Returns true when path is a regular file.
Definition: RADCore.h:81
constexpr LoopStrategy RADEVENT_LOCK
Mutex/condition-variable event loop backend.
Definition: RADCore.h:888
constexpr int VersionMajor
Compile-time RADCore major version.
Definition: RADCore.h:84
VariantType
Runtime type tag for RADVariant.
Definition: RADCore.h:348
@ String
UTF-8 string value.
@ ByteArray
Byte array value.
@ Invalid
No stored value.
@ Bool
Boolean value.
@ Double
Double-precision floating point value.
@ Int64
Signed 64-bit integer value.
ByteOrder
Byte order used by RADDataStream.
Definition: RADCore.h:328
@ BigEndian
Most significant byte first.
@ LittleEndian
Least significant byte first.
void shutdownLogger()
Stops the background logging engine.
constexpr bool hasOpenMode(OpenMode mode, OpenMode flag)
Returns true when mode includes flag.
Definition: RADCore.h:323
auto invokeBlocking(EventLoop &loop, F &&task) -> std::invoke_result_t< F >
Posts task to loop and blocks until the result is available.
Definition: RADCore.h:1037
constexpr OpenMode operator&(OpenMode lhs, OpenMode rhs)
Intersects OpenMode flags.
Definition: RADCore.h:317
Priority
Event loop task priority.
Definition: RADCore.h:892
JsonType
JSON value type tag.
Definition: RADCore.h:493
@ String
JSON string.
@ Array
JSON array.
@ Object
JSON object.
@ Number
JSON number.
@ Null
JSON null.
@ Bool
JSON boolean.
void initLogger()
Starts the background logging engine.
void singleShot(int intervalMs, EventLoop &targetLoop, EventLoop::Task task)
Posts task to targetLoop after intervalMs milliseconds.
constexpr OpenMode operator|(OpenMode lhs, OpenMode rhs)
Combines OpenMode flags.
Definition: RADCore.h:311
const char * runtimeEdition()
Returns the edition used to build the loaded RADCore runtime library.
FileSystemEvent
File watcher event type.
Definition: RADCore.h:1444
@ Created
File or directory was created.
@ Overflow
Watcher event queue overflowed.
@ WatchLost
Watch was lost.
@ Modified
File or directory was modified.
@ Removed
File or directory was removed.
@ Moved
File or directory was moved.
bool runtimeRequiresLicenseKey()
Returns true when the loaded RADCore runtime expects a paid license key.
DataStreamStatus
Read/write status for RADDataStream.
Definition: RADCore.h:336
@ WriteFailed
A write operation failed.
@ ReadFailed
A read operation failed.
@ Ok
No stream error.
@ ReadPastEnd
A read requested more bytes than available.
const char * runtimeAuditStamp()
Returns a stable runtime audit stamp suitable for diagnostics.
void invoke(EventLoop &loop, F &&task)
Posts task to loop.
Definition: RADCore.h:1031
constexpr LoopStrategy RADEVENT_NOLOCK
Low-latency bounded ring event loop backend.
Definition: RADCore.h:890
ProcessState
Process lifecycle state.
Definition: RADCore.h:854
@ FailedToStart
Process failed to start.
@ Running
Process is running.
@ Finished
Process exited.
@ NotRunning
Process has not started.
LogLevel
Logger severity level.
Definition: RADCore.h:1922
OpenMode
Open mode flags shared by RADIODevice, RADFile, and RADBuffer.
Definition: RADCore.h:293
@ ReadOnly
Open for reads.
@ Append
Append writes to the end.
@ WriteOnly
Open for writes.
@ ReadWrite
Open for reads and writes.
@ Text
Text mode hint for platform-specific devices.
@ Truncate
Truncate existing contents on open.
@ NotOpen
Device is not open.
LoopStrategy
Event loop scheduling backend.
Definition: RADCore.h:886
constexpr int VersionMinor
Compile-time RADCore minor version.
Definition: RADCore.h:86
Definition: RADSettings.h:16
Connection record tracked by RADObject for automatic receiver cleanup.
Definition: RADCore.h:895
size_t connectionId
Event-local connection id.
Definition: RADCore.h:897
std::function< void()> disconnectCallback
Callback that disconnects the tracked connection.
Definition: RADCore.h:899
Shared connection state used by Event and Connection.
Definition: RADCore.h:906
std::function< void()> disconnectCallback
Disconnect callback owned by the connection.
Definition: RADCore.h:910
std::atomic_bool connected
True while connected.
Definition: RADCore.h:908
std::shared_ptr< Connection::State > connectionState
Shared connection state.
Definition: RADCore.h:1103
size_t id
Unique handler id.
Definition: RADCore.h:1099
std::function< void(Args...)> dispatch
Dispatch callable.
Definition: RADCore.h:1101
Directory listing entry with basic metadata.
Definition: RADCore.h:708
std::string name
Filename component.
Definition: RADCore.h:712
int64_t modifiedUnixMs
Last modified time in Unix milliseconds when known.
Definition: RADCore.h:718
std::string path
Full path.
Definition: RADCore.h:710
DirectoryEntryType type
Entry type.
Definition: RADCore.h:714
uintmax_t size
File size in bytes when known.
Definition: RADCore.h:716
Definition: RADCore.h:1907
void operator()(Args... args)
Definition: RADCore.h:1909
EventBinder(Event< void(Args...)> &ev)
Definition: RADCore.h:1908
Event< void(Args...)> & targetEvent
Definition: RADCore.h:1907
void(Args...) type
Definition: RADCore.h:879
Definition: RADCore.h:877
Definition: RADCore.h:1913
void operator<<(Event< void()> &targetEvent)
Definition: RADCore.h:1914
Thread affinity snapshot for RADObject event delivery.
Definition: RADCore.h:866
EventLoop * eventLoop
Associated event loop, if any.
Definition: RADCore.h:870
std::thread::id threadId
Target thread id.
Definition: RADCore.h:868