4 Commits 00c53f8127 ... 2a16b476fb

Author SHA1 Message Date
  Ivan Baidakou 2a16b476fb improve performance 2 years ago
  Ivan Baidakou eb9aaffee1 add cancel_event api 2 years ago
  Ivan Baidakou 3dc9d83b82 check and fix event_id uniqueness 2 years ago
  Ivan Baidakou e747338615 refactor events api & events internals 2 years ago

+ 2 - 0
CMakeLists.txt

@@ -14,6 +14,7 @@ if (NOT DEFINED CMAKE_CXX_VISIBILITY_PRESET AND
 endif ()
 
 set(ROTOR_LIGHT_DOC OFF CACHE BOOL "generate docs using doxygen")
+set(ROTOR_LIGHT_ACTOR "uint64_t" CACHE STRING "ActorId type [default: uint64_t]")
 set(ROTOR_LIGHT_TIMEPOINT "int64_t" CACHE STRING "TimePoint type [default: int64_t]")
 set(ROTOR_LIGHT_DURATION "int32_t" CACHE STRING "Duration type [default: int32_t]")
 
@@ -41,6 +42,7 @@ set_target_properties(rotor_light PROPERTIES
     CXX_EXTENSIONS NO
 )
 target_compile_definitions(rotor_light PUBLIC
+    "ROTOR_LIGHT_ACTOR=${ROTOR_LIGHT_ACTOR}"
     "ROTOR_LIGHT_TIMEPOINT=${ROTOR_LIGHT_TIMEPOINT}"
     "ROTOR_LIGHT_DURATION=${ROTOR_LIGHT_DURATION}"
 )

+ 5 - 3
README.md

@@ -32,16 +32,18 @@ care about thread-safety.
 
 |                       | messages/second | binary size
 |:---------------------:|:---------------:|:--------------:
-| host (1)              | ~47.7M          | 13026 bytes
+| host (1)              | ~55.3M          | 13143 bytes
 | STM32-H743ZI          | ~2.3M           | 14330 bytes
-| Arduino Uno R3        | ~10.0K          | 8872 bytes
-| xilinx microblaze (2) | ~58.8K          | 42868 byes
+| Arduino Uno R3 (2)    | ~15.8K          | 6546 bytes
+| xilinx microblaze (3) | ~58.8K          | 42868 byes
 
 All examples can be measured with `examples/ping-pong-throughput.cpp`,
 compiled with `CMAKE_BUILD_TYPE=MinSizeRel` and the stripped
 
 (1) Setup: Intel Core i7-8550U, Void Linux 5.15.
 
+(2) Build with `-DROTOR_LIGHT_ACTOR=uint8_t`
+
 (2) Zynq xc7z020clg400-1, QMTECH development board. Microblaze standard config, hw mul/div instr. enabled, clocking is 50Mhz.
 
 ## license

+ 1 - 1
examples/atmega328p/blink-led-uart.cpp

@@ -43,7 +43,7 @@ struct Blinker : rl::Actor<2> {
 
   void blink() {
     if (next_event) {
-      supervisor->get_planner()->remove_event(next_event, this);
+      supervisor->get_planner()->remove_event(next_event);
     }
     Board::toggle_led();
     send<message::Notify>(0, notifier_id, "blink\r\n");

+ 2 - 1
include/rotor-light/actor.hpp

@@ -35,7 +35,8 @@ struct ActorBase {
   inline void set_fail_policy(FailPolicy value) { fail_policy = value; }
 
   void stop();
-  bool add_event(Duration delta, Callback callback, void *data);
+  EventId add_event(Duration delta, Callback callback, void *data);
+  void cancel_event(EventId event_id);
 
   template <typename MessageType, typename... Args>
   bool send(size_t queue_index, Args... args);

+ 3 - 1
include/rotor-light/definitions.hpp

@@ -22,7 +22,9 @@ enum class FailPolicy {
 
 using MessageTypeId = uint16_t;
 using index_t = uint8_t;
-using ActorId = uint64_t;
+using ActorId = ROTOR_LIGHT_ACTOR;
+using EventId = uint16_t;
+
 static constexpr auto broadcast = std::numeric_limits<ActorId>::max();
 
 struct MessageType {

+ 6 - 3
include/rotor-light/planner.hpp

@@ -13,10 +13,12 @@ struct TimeEvent {
   TimeEvent(TimeEvent &&) = delete;
   TimeEvent(const TimeEvent &) = delete;
 
-  TimeEvent &operator=(const TimeEvent &other);
+  TimeEvent &operator=(const TimeEvent &other) = default;
+
   Callback callback = nullptr;
   void *data;
   TimePoint when = 0;
+  EventId event_id = 0;
 };
 
 struct PlannerBase;
@@ -38,8 +40,8 @@ struct PlannerBase {
   PlannerBase(TimeEvent *events, int32_t events_count);
   PlannerBase(const PlannerBase &) = delete;
   PlannerBase(PlannerBase &&) = delete;
-  bool add_event(TimePoint when, Callback, void *data);
-  void remove_event(TimePoint when, void *data);
+  EventId add_event(TimePoint when, Callback, void *data);
+  void remove_event(EventId event_id);
   EventConsumer consume(TimePoint deadline);
   TimePoint next_event();
 
@@ -49,6 +51,7 @@ private:
   TimeEvent *events;
   int32_t events_count;
   int32_t last_event;
+  EventId next_id;
 };
 
 template <size_t TimeEventsCount> struct Planner : PlannerBase {

+ 1 - 5
include/rotor-light/queue.hpp

@@ -21,15 +21,11 @@ struct ItemGuard {
       : message{message_}, item_queue{item_queue_} {}
   ItemGuard(const ItemGuard &) = delete;
   ItemGuard(ItemGuard &&) = delete;
-  ~ItemGuard();
 
-  ItemGuard &operator=(ItemGuard &&);
+  ItemGuard &operator=(const ItemGuard &) = default;
   inline operator bool() { return message; }
   inline Message &operator*() { return *message; }
 
-  void reset();
-
-private:
   Message *message;
   ItemQueueBase *item_queue;
 };

+ 5 - 1
src/rotor-light/actor.cpp

@@ -62,10 +62,14 @@ void ActorBase::stop() {
   }
 }
 
-bool ActorBase::add_event(Duration delta, Callback callback, void *data) {
+EventId ActorBase::add_event(Duration delta, Callback callback, void *data) {
   assert(supervisor->now && supervisor->planner);
   auto when = supervisor->now() + delta;
   return supervisor->planner->add_event(when, callback, data);
 }
 
+void ActorBase::cancel_event(EventId event_id) {
+  supervisor->planner->remove_event(event_id);
+}
+
 } // namespace rotor_light

+ 48 - 34
src/rotor-light/planner.cpp

@@ -6,56 +6,70 @@
 
 using namespace rotor_light;
 
-TimeEvent &TimeEvent::operator=(const TimeEvent &other) {
-  callback = other.callback;
-  data = other.data;
-  when = other.when;
-  return *this;
-}
-
 PlannerBase::PlannerBase(TimeEvent *events_, int32_t events_count_)
-    : events{events_}, events_count{events_count_}, last_event{-1} {}
+    : events{events_}, events_count{events_count_}, last_event{-1}, next_id{1} {
+}
 
-bool PlannerBase::add_event(TimePoint when, Callback callback, void *data) {
-  if (last_event + 1 < events_count) {
-    int i = 0;
-    // find the insertion point (skip previous events)
-    for (; i <= last_event; ++i) {
-      auto &event = events[i];
-      if (event.when <= when) {
-        continue;
-      }
-      break;
+EventId PlannerBase::add_event(TimePoint when, Callback callback, void *data) {
+  if (last_event + 1 >= events_count) {
+    return 0;
+  }
+  EventId future_id = next_id + 1;
+  bool recheck = false;
+  int i = last_event + 1;
+  // find the insertion point (skip previous events)
+  for (int j = 0; j <= last_event; ++j) {
+    auto &event = events[j];
+    if (event.event_id == future_id) {
+      ++future_id;
+      recheck = true;
     }
-    // copy next events into the next position
-    for (int j = last_event; j >= i; --j) {
-      events[j + 1] = events[j];
+    if (event.when <= when) {
+      continue;
+    } else {
+      i = j;
     }
-    events[i] = TimeEvent{callback, data, when};
-    ++last_event;
-    return true;
   }
-  return false;
+  while (recheck || !future_id) {
+    recheck = false;
+    if (!future_id) {
+      ++future_id;
+    }
+    for (int j = 0; j <= last_event; ++j) {
+      auto &event = events[j];
+      if (event.event_id == future_id) {
+        ++future_id;
+        recheck = true;
+        break;
+      }
+    }
+  }
+  // copy next events into the next position
+  for (int j = last_event; j >= i; --j) {
+    events[j + 1] = events[j];
+  }
+  events[i] = TimeEvent{callback, data, when, next_id};
+  next_id = future_id;
+  ++last_event;
+  return events[i].event_id;
 }
 
-void PlannerBase::remove_event(TimePoint when, void *data) {
+void PlannerBase::remove_event(EventId event_id) {
   int from = -1;
-  int till = -1;
   for (int i = 0; i <= last_event; ++i) {
     auto &e = events[i];
-    if (e.when == when && e.data == data) {
+    if (e.event_id == event_id) {
       if (from == -1) {
         from = i;
+        break;
       }
-      till = i;
     }
   }
-  if (till >= 0) {
-    auto delta = 1 + till - from;
-    for (int i = from; (i <= till) && (i + delta) <= last_event; ++i) {
-      events[i] = events[i + delta];
+  if (from >= 0) {
+    for (int i = from; (i + 1) <= last_event; ++i) {
+      events[i] = events[i + 1];
     }
-    last_event -= delta;
+    --last_event;
   }
 }
 

+ 0 - 0
src/rotor-light/queue.cpp


Some files were not shown because too many files changed in this diff