Просмотр исходного кода

BReactor: implement limit objects

ambrop7 14 лет назад
Родитель
Сommit
7eb58b3a85
2 измененных файлов с 127 добавлено и 0 удалено
  1. 74 0
      system/BReactor.c
  2. 53 0
      system/BReactor.h

+ 74 - 0
system/BReactor.c

@@ -491,6 +491,15 @@ static void wait_for_events (BReactor *bsys)
             }
         }
     }
+    
+    // reset limit objects
+    LinkedList1Node *list_node;
+    while (list_node = LinkedList1_GetFirst(&bsys->active_limits_list)) {
+        BReactorLimit *limit = UPPER_OBJECT(list_node, BReactorLimit, active_limits_list_node);
+        ASSERT(limit->count > 0)
+        limit->count = 0;
+        LinkedList1_Remove(&bsys->active_limits_list, &limit->active_limits_list_node);
+    }
 }
 
 #ifdef BADVPN_USE_WINAPI
@@ -535,6 +544,7 @@ int BReactor_Init (BReactor *bsys)
 {
     BLog(BLOG_DEBUG, "Reactor initializing");
     
+    // set not exiting
     bsys->exiting = 0;
     
     // init jobs
@@ -544,6 +554,9 @@ int BReactor_Init (BReactor *bsys)
     BHeap_Init(&bsys->timers_heap, OFFSET_DIFF(BTimer, absTime, heap_node), (BHeap_comparator)timer_comparator, NULL);
     LinkedList1_Init(&bsys->timers_expired_list);
     
+    // init limits
+    LinkedList1_Init(&bsys->active_limits_list);
+    
     #ifdef BADVPN_USE_WINAPI
     
     bsys->num_handles = 0;
@@ -611,6 +624,7 @@ int BReactor_Init (BReactor *bsys)
     #ifdef BADVPN_USE_KEVENT
     DebugCounter_Init(&bsys->d_kevent_ctr);
     #endif
+    DebugCounter_Init(&bsys->d_limits_ctr);
     
     return 1;
     
@@ -630,6 +644,7 @@ void BReactor_Free (BReactor *bsys)
     ASSERT(!BPendingGroup_HasJobs(&bsys->pending_jobs))
     ASSERT(!BHeap_GetFirst(&bsys->timers_heap))
     ASSERT(LinkedList1_IsEmpty(&bsys->timers_expired_list))
+    ASSERT(LinkedList1_IsEmpty(&bsys->active_limits_list))
     #ifdef BADVPN_USE_WINAPI
     ASSERT(bsys->num_handles == 0)
     #endif
@@ -640,6 +655,7 @@ void BReactor_Free (BReactor *bsys)
     #ifdef BADVPN_USE_KEVENT
     DebugCounter_Free(&bsys->d_kevent_ctr);
     #endif
+    DebugCounter_Free(&bsys->d_limits_ctr);
     #ifdef BADVPN_USE_POLL
     ASSERT(bsys->poll_num_enabled_fds == 0)
     ASSERT(LinkedList1_IsEmpty(&bsys->poll_enabled_fds_list))
@@ -1180,6 +1196,64 @@ void BReactor_SetFileDescriptorEvents (BReactor *bsys, BFileDescriptor *bs, int
 
 #endif
 
+void BReactorLimit_Init (BReactorLimit *o, BReactor *reactor, int limit)
+{
+    DebugObject_Access(&reactor->d_obj);
+    ASSERT(limit > 0)
+    
+    // init arguments
+    o->reactor = reactor;
+    o->limit = limit;
+    
+    // set count zero
+    o->count = 0;
+    
+    DebugCounter_Increment(&reactor->d_limits_ctr);
+    DebugObject_Init(&o->d_obj);
+}
+
+void BReactorLimit_Free (BReactorLimit *o)
+{
+    BReactor *reactor = o->reactor;
+    DebugObject_Free(&o->d_obj);
+    DebugCounter_Decrement(&reactor->d_limits_ctr);
+    
+    // remove from active limits list
+    if (o->count > 0) {
+        LinkedList1_Remove(&reactor->active_limits_list, &o->active_limits_list_node);
+    }
+}
+
+int BReactorLimit_Increment (BReactorLimit *o)
+{
+    BReactor *reactor = o->reactor;
+    DebugObject_Access(&o->d_obj);
+    
+    // check count against limit
+    if (o->count >= o->limit) {
+        return 0;
+    }
+    
+    // increment count
+    o->count++;
+    
+    // if limit was zero, add to active limits list
+    if (o->count == 1) {
+        LinkedList1_Append(&reactor->active_limits_list, &o->active_limits_list_node);
+    }
+    
+    return 1;
+}
+
+void BReactorLimit_SetLimit (BReactorLimit *o, int limit)
+{
+    DebugObject_Access(&o->d_obj);
+    ASSERT(limit > 0)
+    
+    // set limit
+    o->limit = limit;
+}
+
 #ifdef BADVPN_USE_KEVENT
 
 int BReactorKEvent_Init (BReactorKEvent *o, BReactor *reactor, BReactorKEvent_handler handler, void *user, uintptr_t ident, short filter, u_int fflags, intptr_t data)

+ 53 - 0
system/BReactor.h

@@ -225,6 +225,9 @@ typedef struct {
     BHeap timers_heap;
     LinkedList1 timers_expired_list;
     
+    // limits
+    LinkedList1 active_limits_list;
+    
     #ifdef BADVPN_USE_WINAPI
     int num_handles; // number of user handles
     int enabled_num; // number of user handles in the enabled array
@@ -263,6 +266,7 @@ typedef struct {
     #ifdef BADVPN_USE_KEVENT
     DebugCounter d_kevent_ctr;
     #endif
+    DebugCounter d_limits_ctr;
 } BReactor;
 
 /**
@@ -281,8 +285,10 @@ int BReactor_Init (BReactor *bsys) WARN_UNUSED;
  * There must be no {@link BPending} objects using the pending group
  * returned by {@link BReactor_PendingGroup}.
  * There must be no running timers in this reactor.
+ * There must be no limit objects in this reactor.
  * There must be no file descriptors or handles registered
  * with this reactor.
+ * There must be no {@link BReactorKEvent} objects in this reactor.
  *
  * @param bsys the object
  */
@@ -468,6 +474,53 @@ void BReactor_SetFileDescriptorEvents (BReactor *bsys, BFileDescriptor *bs, int
 
 #endif
 
+typedef struct {
+    BReactor *reactor;
+    int limit;
+    int count;
+    LinkedList1Node active_limits_list_node;
+    DebugObject d_obj;
+} BReactorLimit;
+
+/**
+ * Initializes a limit object.
+ * A limit object consists of a counter integer, which is initialized to
+ * zero, is incremented by {@link BReactorLimit_Increment} up to \a limit,
+ * and is reset to zero every time the event loop performs a wait.
+ * If the event loop has processed all detected events, and before performing
+ * a wait, it determines that timers have expired, the counter will not be reset.
+ * 
+ * @param o the object
+ * @param reactor reactor the object is tied to
+ * @param limit maximum counter value. Must be >0.
+ */
+void BReactorLimit_Init (BReactorLimit *o, BReactor *reactor, int limit);
+
+/**
+ * Frees a limit object.
+ * 
+ * @param o the object
+ */
+void BReactorLimit_Free (BReactorLimit *o);
+
+/**
+ * Attempts to increment the counter of a limit object.
+ * 
+ * @param o the object
+ * @return 1 if the counter was lesser than the limit and was incremented,
+ *         0 if the counter was greater or equal to the limit and could not be
+ *           incremented
+ */
+int BReactorLimit_Increment (BReactorLimit *o);
+
+/**
+ * Sets the limit of a limit object.
+ * 
+ * @param o the object
+ * @param limit new limit. Must be >0.
+ */
+void BReactorLimit_SetLimit (BReactorLimit *o, int limit);
+
 #ifdef BADVPN_USE_KEVENT
 
 typedef void (*BReactorKEvent_handler) (void *user, u_int fflags, intptr_t data);