Pārlūkot izejas kodu

splitting server_run s.t. the server can run in one thread with other applications

Stasik0 10 gadi atpakaļ
vecāks
revīzija
fc550a60da
2 mainītis faili ar 73 papildinājumiem un 42 dzēšanām
  1. 14 0
      include/ua_server.h
  2. 59 42
      src/server/ua_server_worker.c

+ 14 - 0
include/ua_server.h

@@ -73,6 +73,20 @@ UA_Logger UA_EXPORT UA_Server_getLogger(UA_Server *server);
  */
 UA_StatusCode UA_EXPORT UA_Server_run(UA_Server *server, UA_UInt16 nThreads, 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, UA_UInt16 nThreads);
+/**
+ * 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);
+/**
+ * One iteration of UA_Server_run (no need to use if you call UA_Server_run)
+ */
+UA_StatusCode UA_EXPORT UA_Server_run_getAndProcessWork(UA_Server *server, UA_Boolean *running);
+
+
 /**
  * Datasources are the interface to local data providers. Implementors of datasources need to
  * provide functions for the callbacks in this structure. After every read, the handle needs to be

+ 59 - 42
src/server/ua_server_worker.c

@@ -436,7 +436,7 @@ static void dispatchDelayedWork(UA_Server *server, void *data /* not used, but n
 /* Main Server Loop */
 /********************/
 
-UA_StatusCode UA_Server_run(UA_Server *server, UA_UInt16 nThreads, UA_Boolean *running) {
+UA_StatusCode UA_Server_run_startup(UA_Server *server, UA_UInt16 nThreads){
 #ifdef UA_MULTITHREADING
     // 1) Prepare the threads
     server->running = running; // the threads need to access the variable
@@ -452,57 +452,57 @@ UA_StatusCode UA_Server_run(UA_Server *server, UA_UInt16 nThreads, UA_Boolean *r
     }
 
     UA_WorkItem processDelayed = {.type = UA_WORKITEMTYPE_METHODCALL,
-                                  .work.methodCall = {.method = dispatchDelayedWork,
-                                                      .data = UA_NULL} };
+            .work.methodCall = {.method = dispatchDelayedWork,
+                    .data = UA_NULL} };
     UA_Server_addRepeatedWorkItem(server, &processDelayed, 10000000, UA_NULL);
 #endif
 
-    // 2) Start the networklayers
-    for(size_t i = 0; i <server->networkLayersSize; i++)
-        server->networkLayers[i].start(server->networkLayers[i].nlHandle, &server->logger);
+// 2) Start the networklayers
+for(size_t i = 0; i <server->networkLayersSize; i++)
+    server->networkLayers[i].start(server->networkLayers[i].nlHandle, &server->logger);
 
-    // 3) The loop
-    while(1) {
-        // 3.1) Process timed work
-        UA_UInt16 timeout = processTimedWork(server);
-
-        // 3.2) Get work from the networklayer and dispatch it
-        for(size_t i = 0; i < server->networkLayersSize; i++) {
-            UA_ServerNetworkLayer *nl = &server->networkLayers[i];
-            UA_WorkItem *work;
-            UA_Int32 workSize;
-            if(*running) {
-            	if(i == server->networkLayersSize-1)
-            		workSize = nl->getWork(nl->nlHandle, &work, timeout);
-            	else
-            		workSize = nl->getWork(nl->nlHandle, &work, 0);
-            } else {
-                workSize = server->networkLayers[i].stop(nl->nlHandle, &work);
-            }
+return UA_STATUSCODE_GOOD;
+}
+
+UA_StatusCode UA_Server_run_getAndProcessWork(UA_Server *server, UA_Boolean *running){
+    // 3.1) Process timed work
+    UA_UInt16 timeout = processTimedWork(server);
+
+    // 3.2) Get work from the networklayer and dispatch it
+    for(size_t i = 0; i < server->networkLayersSize; i++) {
+        UA_ServerNetworkLayer *nl = &server->networkLayers[i];
+        UA_WorkItem *work;
+        UA_Int32 workSize;
+        if(*running) {
+            if(i == server->networkLayersSize-1)
+                workSize = nl->getWork(nl->nlHandle, &work, timeout);
+            else
+                workSize = nl->getWork(nl->nlHandle, &work, 0);
+        } else {
+            workSize = server->networkLayers[i].stop(nl->nlHandle, &work);
+        }
 
 #ifdef UA_MULTITHREADING
-            // Filter out delayed work
-            for(UA_Int32 k=0;k<workSize;k++) {
-                if(work[k].type != UA_WORKITEMTYPE_DELAYEDMETHODCALL)
-                    continue;
-                addDelayedWork(server, work[k]);
-                work[k].type = UA_WORKITEMTYPE_NOTHING;
-            }
-            dispatchWork(server, workSize, work);
-            if(workSize > 0)
-                pthread_cond_broadcast(&server->dispatchQueue_condition); 
+// Filter out delayed work
+for(UA_Int32 k=0;k<workSize;k++) {
+    if(work[k].type != UA_WORKITEMTYPE_DELAYEDMETHODCALL)
+        continue;
+    addDelayedWork(server, work[k]);
+    work[k].type = UA_WORKITEMTYPE_NOTHING;
+}
+dispatchWork(server, workSize, work);
+if(workSize > 0)
+    pthread_cond_broadcast(&server->dispatchQueue_condition);
 #else
-            processWork(server, work, workSize);
-            if(workSize > 0)
-                UA_free(work);
+processWork(server, work, workSize);
+if(workSize > 0)
+    UA_free(work);
 #endif
-        }
-
-        // 3.3) Exit?
-        if(!*running)
-            break;
     }
+    return UA_STATUSCODE_GOOD;
+}
 
+UA_StatusCode UA_Server_run_shutdown(UA_Server *server){
 #ifdef UA_MULTITHREADING
     // 4) Clean up: Wait until all worker threads finish, then empty the
     // dispatch queue, then process the remaining delayed work
@@ -518,3 +518,20 @@ UA_StatusCode UA_Server_run(UA_Server *server, UA_UInt16 nThreads, UA_Boolean *r
 
     return UA_STATUSCODE_GOOD;
 }
+
+UA_StatusCode UA_Server_run(UA_Server *server, UA_UInt16 nThreads, UA_Boolean *running) {
+    UA_Server_run_startup(server, nThreads);
+
+    // 3) The loop
+    while(1) {
+        UA_Server_run_getAndProcessWork(server, running);
+
+        // 3.3) Exit?
+        if(!*running)
+            break;
+    }
+
+    UA_Server_run_shutdown(server);
+
+    return UA_STATUSCODE_GOOD;
+}