Ver código fonte

return the remaining timeout in UA_Server_run_iterate

Julius Pfrommer 9 anos atrás
pai
commit
f7f98bf3f3
2 arquivos alterados com 44 adições e 26 exclusões
  1. 18 5
      include/ua_server.h
  2. 26 21
      src/server/ua_server_worker.c

+ 18 - 5
include/ua_server.h

@@ -67,20 +67,33 @@ UA_Server UA_EXPORT * UA_Server_new(const UA_ServerConfig config);
 void UA_EXPORT UA_Server_delete(UA_Server *server);
 
 /**
- * Runs the main loop of the server. In each iteration, this calls into the networklayers to see if
- * jobs have arrived and checks if repeated jobs need to be triggered.
+ * Runs the main loop of the server. In each iteration, this calls into the
+ * networklayers to see if jobs have arrived and checks if repeated jobs need to
+ * be triggered.
+ *
+ * @param server The server object.
+ * @param running The loop is run as long as *running is true. Otherwise, the server shuts down.
+ * @return Returns the statuscode of the UA_Server_run_shutdown method
  */
 UA_StatusCode UA_EXPORT UA_Server_run(UA_Server *server, volatile UA_Boolean *running);
 
 /** The prologue part of UA_Server_run (no need to use if you call UA_Server_run) */
 UA_StatusCode UA_EXPORT UA_Server_run_startup(UA_Server *server);
 
-/** One iteration of UA_Server_run (no need to use if you call UA_Server_run) */
-UA_StatusCode UA_EXPORT UA_Server_run_iterate(UA_Server *server);
-
 /** The epilogue part of UA_Server_run (no need to use if you call UA_Server_run) */
 UA_StatusCode UA_EXPORT UA_Server_run_shutdown(UA_Server *server);
 
+/**
+ * Executes a single iteration of the server's main loop.
+ *
+ * @param server The server object.
+ * @param waitInternal Should we wait for messages in the networklayer?
+ *        Otherwise, the timouts for the networklayers are set to zero.
+ *        The default max wait time is 50millisec.
+ * @return Returns how long we can wait until the next scheduled job (in millisec)
+ */
+UA_UInt16 UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal);
+
 /**
  * @param server The server object.
  * @param job The job that shall be added.

+ 26 - 21
src/server/ua_server_worker.c

@@ -34,7 +34,7 @@
  * 
  */
 
-#define MAXTIMEOUT 50000 // max timeout in microsec until the next main loop iteration
+#define MAXTIMEOUT 50 // max timeout in millisec until the next main loop iteration
 #define BATCHSIZE 20 // max number of jobs that are dispatched at once to workers
 
 static void processJobs(UA_Server *server, UA_Job *jobs, size_t jobsSize) {
@@ -252,7 +252,7 @@ UA_StatusCode UA_Server_addRepeatedJob(UA_Server *server, UA_Job job, UA_UInt32
     /* the interval needs to be at least 5ms */
     if(interval < 5)
         return UA_STATUSCODE_BADINTERNALERROR;
-    interval *= 10000; // from ms to 100ns resolution
+    interval *= (UA_UInt32)UA_MSEC_TO_DATETIME; // from ms to 100ns resolution
 
 #ifdef UA_ENABLE_MULTITHREADING
     struct AddRepeatedJob *arw = UA_malloc(sizeof(struct AddRepeatedJob));
@@ -290,11 +290,9 @@ UA_StatusCode UA_Server_addRepeatedJob(UA_Server *server, UA_Job job, UA_UInt32
     return UA_STATUSCODE_GOOD;
 }
 
-/* Returns the timeout until the next repeated job in ms */
-static UA_UInt16 processRepeatedJobs(UA_Server *server) {
-    UA_DateTime current = UA_DateTime_nowMonotonic();
+/* Returns the next datetime when a repeated job is scheduled */
+static UA_DateTime processRepeatedJobs(UA_Server *server, UA_DateTime current) {
     struct RepeatedJobs *tw = NULL;
-
     while((tw = LIST_FIRST(&server->repeatedJobs)) != NULL) {
         if(tw->nextTime > current)
             break;
@@ -338,13 +336,10 @@ static UA_UInt16 processRepeatedJobs(UA_Server *server) {
     // check if the next repeated job is sooner than the usual timeout
     // calc in 32 bit must be ok
     struct RepeatedJobs *first = LIST_FIRST(&server->repeatedJobs);
-    UA_UInt16 timeout = MAXTIMEOUT;
-    if(first) {
-        timeout = (UA_UInt16)((first->nextTime - current) / 10);
-        if(timeout > MAXTIMEOUT)
-            return MAXTIMEOUT;
-    }
-    return timeout;
+    UA_DateTime next = current + (MAXTIMEOUT * UA_MSEC_TO_DATETIME);
+    if(first && first->nextTime < next)
+        next = first->nextTime;
+    return next;
 }
 
 /* Call this function only from the main loop! */
@@ -595,19 +590,26 @@ UA_StatusCode UA_Server_run_startup(UA_Server *server) {
     return result;
 }
 
-UA_StatusCode UA_Server_run_iterate(UA_Server *server) {
+UA_UInt16 UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
 #ifdef UA_ENABLE_MULTITHREADING
-    processMainLoopJobs(server); /* Run work assigned for the main thread */
+    /* Run work assigned for the main thread */
+    processMainLoopJobs(server);
 #endif
-    UA_UInt16 timeout = processRepeatedJobs(server); /* Process repeated work */
+    /* Process repeated work */
+    UA_DateTime now = UA_DateTime_nowMonotonic();
+    UA_DateTime nextRepeated = processRepeatedJobs(server, now);
+
+    UA_UInt16 timeout = 0;
+    if(waitInternal && nextRepeated > now)
+        timeout = (UA_UInt16)((nextRepeated - now) / UA_MSEC_TO_DATETIME);
 
     /* Get work from the networklayer */
     for(size_t i = 0; i < server->config.networkLayersSize; i++) {
         UA_ServerNetworkLayer *nl = &server->config.networkLayers[i];
         UA_Job *jobs;
         size_t jobsSize;
+        /* only the last networklayer waits on the tieout */
         if(i == server->config.networkLayersSize-1)
-            /* only the last networklayer waits on the tieout */
             jobsSize = nl->getJobs(nl, &jobs, timeout);
         else
             jobsSize = nl->getJobs(nl, &jobs, 0);
@@ -621,8 +623,7 @@ UA_StatusCode UA_Server_run_iterate(UA_Server *server) {
             jobs[k].type = UA_JOBTYPE_NOTHING;
         }
 
-        dispatchJobs(server, jobs, jobsSize); /* Dispatch work to worker threads */
-
+        dispatchJobs(server, jobs, jobsSize);
         /* Wake up worker threads */
         if(jobsSize > 0)
             pthread_cond_broadcast(&server->dispatchQueue_condition);
@@ -633,7 +634,11 @@ UA_StatusCode UA_Server_run_iterate(UA_Server *server) {
 #endif
     }
 
-    return UA_STATUSCODE_GOOD;
+    now = UA_DateTime_nowMonotonic();
+    timeout = 0;
+    if(nextRepeated > now)
+        timeout = (UA_UInt16)((nextRepeated - now) / UA_MSEC_TO_DATETIME);
+    return timeout;
 }
 
 UA_StatusCode UA_Server_run_shutdown(UA_Server *server) {
@@ -670,6 +675,6 @@ UA_StatusCode UA_Server_run(UA_Server *server, volatile UA_Boolean *running) {
     if(retval != UA_STATUSCODE_GOOD)
         return retval;
     while(*running)
-            UA_Server_run_iterate(server);
+        UA_Server_run_iterate(server, UA_TRUE);
     return UA_Server_run_shutdown(server);
 }