Pārlūkot izejas kodu

system: BReactor: don't store a callback void pointer in BSmallTimer, instead just pass the BSmallTimer pointer to the
callback.

To preserver memory efficiency, switch from SAvl to CAvl and reorder members. To preserve time efficiency, keep a flag indicating
whether a timer is really a BTimer or not, and directly call the BTimer_handler if it is (as oppossed to having an internal
callback which calls the BTimer_handler). Additionally, store the timer state in a new member instead of in absTime, as the
new layout allows so without increasing the size of BSmallTimer.

ambrop7 13 gadi atpakaļ
vecāks
revīzija
da424e04ab
4 mainītis faili ar 114 papildinājumiem un 78 dzēšanām
  1. 4 3
      ncd/ncd.c
  2. 67 46
      system/BReactor_badvpn.c
  3. 30 22
      system/BReactor_badvpn.h
  4. 13 7
      system/BReactor_badvpn_timerstree.h

+ 4 - 3
ncd/ncd.c

@@ -170,7 +170,7 @@ static void process_schedule_work (struct process *p);
 static void process_work_job_handler (struct process *p);
 static int replace_placeholders_callback (void *arg, int plid, NCDValMem *mem, NCDValRef *out);
 static void process_advance (struct process *p);
-static void process_wait_timer_handler (struct process *p);
+static void process_wait_timer_handler (BSmallTimer *timer);
 static int process_find_object (struct process *p, int pos, const char *name, NCDObject *out_object);
 static int process_resolve_object_expr (struct process *p, int pos, const char *names, size_t num_names, NCDObject *out_object);
 static int process_resolve_variable_expr (struct process *p, int pos, const char *names, size_t num_names, NCDValMem *mem, NCDValRef *out_value);
@@ -725,7 +725,7 @@ int process_new (NCDInterpProcess *iprocess, NCDModuleProcess *module_process)
     }
     
     // init timer
-    BSmallTimer_Init(&p->wait_timer, (BSmallTimer_handler)process_wait_timer_handler, p);
+    BSmallTimer_Init(&p->wait_timer, process_wait_timer_handler);
     
     // init work job
     BSmallPending_Init(&p->work_job, BReactor_PendingGroup(&reactor), (BSmallPending_handler)process_work_job_handler, p);
@@ -1101,8 +1101,9 @@ fail0:
     process_schedule_work(p);
 }
 
-void process_wait_timer_handler (struct process *p)
+void process_wait_timer_handler (BSmallTimer *timer)
 {
+    struct process *p = UPPER_OBJECT(timer, struct process, wait_timer);
     process_assert_pointers(p);
     ASSERT(p->ap == p->fp)
     ASSERT(!process_have_child(p))

+ 67 - 46
system/BReactor_badvpn.c

@@ -54,10 +54,9 @@
 #define KEVENT_TAG_FD 1
 #define KEVENT_TAG_KEVENT 2
 
-#define BTIMER_INACTIVE_TIME (BTIME_MIN + 0)
-#define BTIMER_EXPIRED_TIME (BTIME_MIN + 1)
-#define BTIMER_MIN_RUNNING_TIME (BTIME_MIN + 2)
-#define BTIMER_IS_RUNNING_TIME(x) ((x) >= BTIMER_MIN_RUNNING_TIME)
+#define TIMER_STATE_INACTIVE 1
+#define TIMER_STATE_RUNNING 2
+#define TIMER_STATE_EXPIRED 3
 
 static int compare_timers (BSmallTimer *t1, BSmallTimer *t2)
 {
@@ -70,16 +69,23 @@ static int compare_timers (BSmallTimer *t1, BSmallTimer *t2)
 }
 
 #include "BReactor_badvpn_timerstree.h"
-#include <structure/SAvl_impl.h>
+#include <structure/CAvl_impl.h>
+
+static void assert_timer (BSmallTimer *bt)
+{
+    ASSERT(bt->state == TIMER_STATE_INACTIVE || bt->state == TIMER_STATE_RUNNING ||
+           bt->state == TIMER_STATE_EXPIRED)
+}
 
 static int move_expired_timers (BReactor *bsys, btime_t now)
 {
     int moved = 0;
     
     // move timed out timers to the expired list
+    BReactor__TimersTreeRef ref;
     BSmallTimer *timer;
-    while (timer = BReactor__TimersTree_GetFirst(&bsys->timers_tree, 0)) {
-        ASSERT(BTIMER_IS_RUNNING_TIME(timer->absTime))
+    while (timer = (ref = BReactor__TimersTree_GetFirst(&bsys->timers_tree, 0)).link) {
+        ASSERT(timer->state == TIMER_STATE_RUNNING)
         
         // if it's in the future, stop
         if (timer->absTime > now) {
@@ -88,13 +94,13 @@ static int move_expired_timers (BReactor *bsys, btime_t now)
         moved = 1;
         
         // remove from running timers tree
-        BReactor__TimersTree_Remove(&bsys->timers_tree, 0, timer);
+        BReactor__TimersTree_Remove(&bsys->timers_tree, 0, ref);
         
         // add to expired timers list
-        LinkedList1_Append(&bsys->timers_expired_list, &timer->list_node);
+        LinkedList1_Append(&bsys->timers_expired_list, &timer->u.list_node);
 
         // set expired
-        timer->absTime = BTIMER_EXPIRED_TIME;
+        timer->state = TIMER_STATE_EXPIRED;
     }
 
     return moved;
@@ -102,25 +108,27 @@ static int move_expired_timers (BReactor *bsys, btime_t now)
 
 static void move_first_timers (BReactor *bsys)
 {
+    BReactor__TimersTreeRef ref;
+    
     // get the time of the first timer
-    BSmallTimer *first_timer = BReactor__TimersTree_GetFirst(&bsys->timers_tree, 0);
+    BSmallTimer *first_timer = (ref = BReactor__TimersTree_GetFirst(&bsys->timers_tree, 0)).link;
     ASSERT(first_timer)
-    ASSERT(BTIMER_IS_RUNNING_TIME(first_timer->absTime))
+    ASSERT(first_timer->state == TIMER_STATE_RUNNING)
     btime_t first_time = first_timer->absTime;
     
     // remove from running timers tree
-    BReactor__TimersTree_Remove(&bsys->timers_tree, 0, first_timer);
+    BReactor__TimersTree_Remove(&bsys->timers_tree, 0, ref);
     
     // add to expired timers list
-    LinkedList1_Append(&bsys->timers_expired_list, &first_timer->list_node);
+    LinkedList1_Append(&bsys->timers_expired_list, &first_timer->u.list_node);
     
     // set expired
-    first_timer->absTime = BTIMER_EXPIRED_TIME;
+    first_timer->state = TIMER_STATE_EXPIRED;
     
     // also move other timers with the same timeout
     BSmallTimer *timer;
-    while (timer = BReactor__TimersTree_GetFirst(&bsys->timers_tree, 0)) {
-        ASSERT(BTIMER_IS_RUNNING_TIME(timer->absTime))
+    while (timer = (ref = BReactor__TimersTree_GetFirst(&bsys->timers_tree, 0)).link) {
+        ASSERT(timer->state == TIMER_STATE_RUNNING)
         ASSERT(timer->absTime >= first_time)
         
         // if it's in the future, stop
@@ -129,13 +137,13 @@ static void move_first_timers (BReactor *bsys)
         }
         
         // remove from running timers tree
-        BReactor__TimersTree_Remove(&bsys->timers_tree, 0, timer);
+        BReactor__TimersTree_Remove(&bsys->timers_tree, 0, ref);
         
         // add to expired timers list
-        LinkedList1_Append(&bsys->timers_expired_list, &timer->list_node);
+        LinkedList1_Append(&bsys->timers_expired_list, &timer->u.list_node);
         
         // set expired
-        timer->absTime = BTIMER_EXPIRED_TIME;
+        timer->state = TIMER_STATE_EXPIRED;
     }
 }
 
@@ -303,9 +311,9 @@ static void wait_for_events (BReactor *bsys)
     btime_t now = 0; // to remove warning
     
     // compute timeout
-    BSmallTimer *first_timer = BReactor__TimersTree_GetFirst(&bsys->timers_tree, 0);
+    BSmallTimer *first_timer = BReactor__TimersTree_GetFirst(&bsys->timers_tree, 0).link;
     if (first_timer) {
-        ASSERT(BTIMER_IS_RUNNING_TIME(first_timer->absTime))
+        ASSERT(first_timer->state == TIMER_STATE_RUNNING)
         
         // get current time
         now = btime_gettime();
@@ -552,21 +560,26 @@ void BFileDescriptor_Init (BFileDescriptor *bs, int fd, BFileDescriptor_handler
 
 #endif
 
-void BSmallTimer_Init (BSmallTimer *bt, BSmallTimer_handler handler, void *handler_pointer)
+void BSmallTimer_Init (BSmallTimer *bt, BSmallTimer_handler handler)
 {
-    bt->handler = handler;
-    bt->handler_pointer = handler_pointer;
-    bt->absTime = BTIMER_INACTIVE_TIME;
+    bt->handler.small = handler;
+    bt->state = TIMER_STATE_INACTIVE;
+    bt->is_small = 1;
 }
 
 int BSmallTimer_IsRunning (BSmallTimer *bt)
 {
-    return (bt->absTime != BTIMER_INACTIVE_TIME);
+    assert_timer(bt);
+    
+    return (bt->state != TIMER_STATE_INACTIVE);
 }
 
 void BTimer_Init (BTimer *bt, btime_t msTime, BTimer_handler handler, void *user)
 {
-    BSmallTimer_Init(&bt->base, handler, user);
+    bt->base.handler.heavy = handler;
+    bt->base.state = TIMER_STATE_INACTIVE;
+    bt->base.is_small = 0;
+    bt->user = user;
     bt->msTime = msTime;
 }
 
@@ -764,18 +777,23 @@ int BReactor_Exec (BReactor *bsys)
         // dispatch timer
         LinkedList1Node *list_node = LinkedList1_GetFirst(&bsys->timers_expired_list);
         if (list_node) {
-            BSmallTimer *timer = UPPER_OBJECT(list_node, BSmallTimer, list_node);
-            ASSERT(timer->absTime == BTIMER_EXPIRED_TIME)
+            BSmallTimer *timer = UPPER_OBJECT(list_node, BSmallTimer, u.list_node);
+            ASSERT(timer->state == TIMER_STATE_EXPIRED)
             
             // remove from expired list
-            LinkedList1_Remove(&bsys->timers_expired_list, &timer->list_node);
+            LinkedList1_Remove(&bsys->timers_expired_list, &timer->u.list_node);
             
             // set inactive
-            timer->absTime = BTIMER_INACTIVE_TIME;
+            timer->state = TIMER_STATE_INACTIVE;
             
             // call handler
             BLog(BLOG_DEBUG, "Dispatching timer");
-            timer->handler(timer->handler_pointer);
+            if (timer->is_small) {
+                timer->handler.small(timer);
+            } else {
+                BTimer *btimer = UPPER_OBJECT(timer, BTimer, base);
+                timer->handler.heavy(btimer->user);
+            }
             continue;
         }
         
@@ -973,6 +991,7 @@ void BReactor_Quit (BReactor *bsys, int code)
 
 void BReactor_SetSmallTimer (BReactor *bsys, BSmallTimer *bt, int mode, btime_t time)
 {
+    assert_timer(bt);
     ASSERT(mode == BTIMER_SET_ABSOLUTE || mode == BTIMER_SET_RELATIVE)
     
     // unlink it if it's already in the list
@@ -983,35 +1002,37 @@ void BReactor_SetSmallTimer (BReactor *bsys, BSmallTimer *bt, int mode, btime_t
         time = btime_add(btime_gettime(), time);
     }
     
-    // don't allow reserved times
-    if (!BTIMER_IS_RUNNING_TIME(time)) {
-        time = BTIMER_MIN_RUNNING_TIME;
-    }
-
-    // initialize timer
+    // set time
     bt->absTime = time;
-
+    
+    // set running
+    bt->state = TIMER_STATE_RUNNING;
+    
     // insert to running timers tree
-    int res = BReactor__TimersTree_Insert(&bsys->timers_tree, 0, bt, NULL);
+    BReactor__TimersTreeRef ref = {bt, bt};
+    int res = BReactor__TimersTree_Insert(&bsys->timers_tree, 0, ref, NULL);
     ASSERT_EXECUTE(res)
 }
 
 void BReactor_RemoveSmallTimer (BReactor *bsys, BSmallTimer *bt)
 {
-    if (bt->absTime == BTIMER_INACTIVE_TIME) {
+    assert_timer(bt);
+    
+    if (bt->state == TIMER_STATE_INACTIVE) {
         return;
     }
 
-    if (bt->absTime == BTIMER_EXPIRED_TIME) {
+    if (bt->state == TIMER_STATE_EXPIRED) {
         // remove from expired list
-        LinkedList1_Remove(&bsys->timers_expired_list, &bt->list_node);
+        LinkedList1_Remove(&bsys->timers_expired_list, &bt->u.list_node);
     } else {
         // remove from running tree
-        BReactor__TimersTree_Remove(&bsys->timers_tree, 0, bt);
+        BReactor__TimersTreeRef ref = {bt, bt};
+        BReactor__TimersTree_Remove(&bsys->timers_tree, 0, ref);
     }
 
     // set inactive
-    bt->absTime = BTIMER_INACTIVE_TIME;
+    bt->state = TIMER_STATE_INACTIVE;
 }
 
 void BReactor_SetTimer (BReactor *bsys, BTimer *bt)

+ 30 - 22
system/BReactor_badvpn.h

@@ -63,14 +63,15 @@
 #include <misc/debugcounter.h>
 #include <base/DebugObject.h>
 #include <structure/LinkedList1.h>
-#include <structure/SAvl.h>
+#include <structure/CAvl.h>
 #include <system/BTime.h>
 #include <base/BPending.h>
 
 struct BSmallTimer_t;
+typedef struct BSmallTimer_t *BReactor_timerstree_link;
 
 #include "BReactor_badvpn_timerstree.h"
-#include <structure/SAvl_decl.h>
+#include <structure/CAvl_decl.h>
 
 /**
  * Handler function invoked when the timer expires.
@@ -79,21 +80,39 @@ struct BSmallTimer_t;
  * This function is being called from within the timer's previosly
  * associated reactor.
  *
- * @param user value passed to {@link BSmallTimer_Init}
+ * @param timer pointer to the timer. Use the {@link UPPER_OBJECT} macro
+ *              to obtain the pointer to the containing structure.
  */
-typedef void (*BSmallTimer_handler) (void *user);
+typedef void (*BSmallTimer_handler) (struct BSmallTimer_t *timer);
+
+/**
+ * Handler function invoked when the timer expires.
+ * The timer was in running state.
+ * The timer enters not running state before this function is invoked.
+ * This function is being called from within the timer's previosly
+ * associated reactor.
+ *
+ * @param user value passed to {@link BTimer_Init}
+ */
+typedef void (*BTimer_handler) (void *user);
 
 /**
  * Timer object used with {@link BReactor}.
  */
 typedef struct BSmallTimer_t {
-    BSmallTimer_handler handler;
-    void *handler_pointer;
-    btime_t absTime;
     union {
-        BReactor__TimersTreeNode tree_node;
+        BSmallTimer_handler small;
+        BTimer_handler heavy;
+    } handler;
+    union {
         LinkedList1Node list_node;
-    };
+        struct BSmallTimer_t *tree_child[2];
+    } u;
+    struct BSmallTimer_t *tree_parent;
+    btime_t absTime;
+    int8_t tree_balance;
+    uint8_t state;
+    uint8_t is_small;
 } BSmallTimer;
 
 /**
@@ -102,9 +121,8 @@ typedef struct BSmallTimer_t {
  *
  * @param bt the object
  * @param handler handler function invoked when the timer expires
- * @param user value to pass to the handler function
  */
-void BSmallTimer_Init (BSmallTimer *bt, BSmallTimer_handler handler, void *user);
+void BSmallTimer_Init (BSmallTimer *bt, BSmallTimer_handler handler);
 
 /**
  * Checks if the timer is running.
@@ -114,23 +132,13 @@ void BSmallTimer_Init (BSmallTimer *bt, BSmallTimer_handler handler, void *user)
  */
 int BSmallTimer_IsRunning (BSmallTimer *bt);
 
-/**
- * Handler function invoked when the timer expires.
- * The timer was in running state.
- * The timer enters not running state before this function is invoked.
- * This function is being called from within the timer's previosly
- * associated reactor.
- *
- * @param user value passed to {@link BTimer_Init}
- */
-typedef void (*BTimer_handler) (void *user);
-
 /**
  * Timer object used with {@link BReactor}. This is a legacy wrapper
  * around {@link BSmallTimer} with an extra field for the default time.
  */
 typedef struct {
     BSmallTimer base;
+    void *user;
     btime_t msTime;
 } BTimer;
 

+ 13 - 7
system/BReactor_badvpn_timerstree.h

@@ -1,7 +1,13 @@
-#define SAVL_PARAM_NAME BReactor__TimersTree
-#define SAVL_PARAM_FEATURE_COUNTS 0
-#define SAVL_PARAM_FEATURE_NOKEYS 1
-#define SAVL_PARAM_TYPE_ENTRY struct BSmallTimer_t
-#define SAVL_PARAM_TYPE_ARG int
-#define SAVL_PARAM_FUN_COMPARE_ENTRIES(arg, entry1, entry2) compare_timers((entry1), (entry2))
-#define SAVL_PARAM_MEMBER_NODE tree_node
+#define CAVL_PARAM_NAME BReactor__TimersTree
+#define CAVL_PARAM_FEATURE_COUNTS 0
+#define CAVL_PARAM_FEATURE_KEYS_ARE_INDICES 0
+#define CAVL_PARAM_FEATURE_NOKEYS 1
+#define CAVL_PARAM_TYPE_ENTRY struct BSmallTimer_t
+#define CAVL_PARAM_TYPE_LINK BReactor_timerstree_link
+#define CAVL_PARAM_TYPE_ARG int
+#define CAVL_PARAM_VALUE_NULL ((BReactor_timerstree_link)NULL)
+#define CAVL_PARAM_FUN_DEREF(arg, link) (link)
+#define CAVL_PARAM_FUN_COMPARE_ENTRIES(arg, entry1, entry2) compare_timers((entry1).link, (entry2).link)
+#define CAVL_PARAM_MEMBER_CHILD u.tree_child
+#define CAVL_PARAM_MEMBER_BALANCE tree_balance
+#define CAVL_PARAM_MEMBER_PARENT tree_parent