Browse Source

BReactor: add ability to execute jobs directly until a mark job is reached. Allows integration of third-party software that does
not work with the jobs system.

ambrop7 15 years ago
parent
commit
bf16d03931
4 changed files with 57 additions and 0 deletions
  1. 12 0
      system/BPending.c
  2. 8 0
      system/BPending.h
  3. 17 0
      system/BReactor.c
  4. 20 0
      system/BReactor.h

+ 12 - 0
system/BPending.c

@@ -73,6 +73,18 @@ void BPendingGroup_ExecuteJob (BPendingGroup *g)
     return;
 }
 
+BPending * BPendingGroup_PeekJob (BPendingGroup *g)
+{
+    DebugObject_Access(&g->d_obj);
+    
+    LinkedList2Node *node = LinkedList2_GetLast(&g->jobs);
+    if (!node) {
+        return NULL;
+    }
+    
+    return UPPER_OBJECT(node, BPending, pending_node);
+}
+
 void BPending_Init (BPending *o, BPendingGroup *g, BPending_handler handler, void *user)
 {
     // init arguments

+ 8 - 0
system/BPending.h

@@ -96,6 +96,14 @@ int BPendingGroup_HasJobs (BPendingGroup *g);
  */
 void BPendingGroup_ExecuteJob (BPendingGroup *g);
 
+/**
+ * Returns the top job on the job list, or NULL if there are none.
+ * 
+ * @param g the object
+ * @return the top job if there is at least one job, NULL if not
+ */
+BPending * BPendingGroup_PeekJob (BPendingGroup *g);
+
 /**
  * Initializes the object.
  * The object is initialized in not set state.

+ 17 - 0
system/BReactor.c

@@ -582,6 +582,23 @@ BPendingGroup * BReactor_PendingGroup (BReactor *bsys)
     return &bsys->pending_jobs;
 }
 
+int BReactor_Synchronize (BReactor *bsys, BPending *ref)
+{
+    ASSERT(ref)
+    
+    while (!bsys->exiting) {
+        ASSERT(BPendingGroup_HasJobs(&bsys->pending_jobs))
+        
+        if (BPendingGroup_PeekJob(&bsys->pending_jobs) == ref) {
+            return 1;
+        }
+        
+        BPendingGroup_ExecuteJob(&bsys->pending_jobs);
+    }
+    
+    return 0;
+}
+
 #ifdef BADVPN_USE_WINAPI
 
 int BReactor_AddHandle (BReactor *bsys, BHandle *bh)

+ 20 - 0
system/BReactor.h

@@ -308,6 +308,26 @@ void BReactor_RemoveTimer (BReactor *bsys, BTimer *bt);
  */
 BPendingGroup * BReactor_PendingGroup (BReactor *bsys);
 
+/**
+ * Executes pending jobs until either:
+ *   - the reference job is reached, or
+ *   - {@link BReactor_Quit} is called.
+ * The reference job must be reached before the job list empties.
+ * The reference job will not be executed.
+ * 
+ * WARNING: Use with care. This should only be used to to work around third-party software
+ * that does not integrade into the jobs system. In particular, you should think about:
+ *   - the effects the jobs to be executed may have, and
+ *   - the environment those jobs expect to be executed in.
+ * 
+ * @param bsys the object
+ * @param ref reference job. It is not accessed in any way, only its address is compared to
+ *            pending jobs before they are executed.
+ * @return 1 if the reference job was reached,
+ *         0 if {@link BReactor_Quit} was called (either while executing a job, or before)
+ */
+int BReactor_Synchronize (BReactor *bsys, BPending *ref);
+
 #ifdef BADVPN_USE_WINAPI
 
 /**