|
@@ -103,16 +103,19 @@ workerLoop(UA_Worker *worker) {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-emptyDispatchQueue(UA_Server *server) {
|
|
|
- pthread_mutex_lock(&server->dispatchQueue_accessMutex);
|
|
|
- WorkerCallback *dc;
|
|
|
- while((dc = SIMPLEQ_FIRST(&server->dispatchQueue)) != NULL) {
|
|
|
+void UA_Server_cleanupDispatchQueue(UA_Server *server) {
|
|
|
+ while(true) {
|
|
|
+ pthread_mutex_lock(&server->dispatchQueue_accessMutex);
|
|
|
+ WorkerCallback *dc = SIMPLEQ_FIRST(&server->dispatchQueue);
|
|
|
+ if(!dc) {
|
|
|
+ pthread_mutex_unlock(&server->dispatchQueue_accessMutex);
|
|
|
+ break;
|
|
|
+ }
|
|
|
SIMPLEQ_REMOVE_HEAD(&server->dispatchQueue, next);
|
|
|
+ pthread_mutex_unlock(&server->dispatchQueue_accessMutex);
|
|
|
dc->callback(server, dc->data);
|
|
|
UA_free(dc);
|
|
|
}
|
|
|
- pthread_mutex_unlock(&server->dispatchQueue_accessMutex);
|
|
|
}
|
|
|
|
|
|
#endif
|
|
@@ -169,6 +172,19 @@ UA_Server_workerCallback(UA_Server *server, UA_ServerCallback callback,
|
|
|
* 3. Check regularly if the callback is ready by adding it back to the dispatch
|
|
|
* queue. */
|
|
|
|
|
|
+/* Delayed callback to free the subscription memory */
|
|
|
+static void
|
|
|
+freeCallback(UA_Server *server, void *data) {
|
|
|
+ UA_free(data);
|
|
|
+}
|
|
|
+
|
|
|
+/* TODO: Delayed free should never fail. This can be achieved by adding a prefix
|
|
|
+ * with the list pointers */
|
|
|
+UA_StatusCode
|
|
|
+UA_Server_delayedFree(UA_Server *server, void *data) {
|
|
|
+ return UA_Server_delayedCallback(server, freeCallback, data);
|
|
|
+}
|
|
|
+
|
|
|
#ifndef UA_ENABLE_MULTITHREADING
|
|
|
|
|
|
typedef struct UA_DelayedCallback {
|
|
@@ -191,8 +207,7 @@ UA_Server_delayedCallback(UA_Server *server, UA_ServerCallback callback,
|
|
|
return UA_STATUSCODE_GOOD;
|
|
|
}
|
|
|
|
|
|
-static void
|
|
|
-processDelayedCallbacks(UA_Server *server) {
|
|
|
+void UA_Server_cleanupDelayedCallbacks(UA_Server *server) {
|
|
|
UA_DelayedCallback *dc, *dc_tmp;
|
|
|
SLIST_FOREACH_SAFE(dc, &server->delayedCallbacks, next, dc_tmp) {
|
|
|
SLIST_REMOVE(&server->delayedCallbacks, dc, UA_DelayedCallback, next);
|
|
@@ -359,9 +374,10 @@ UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
|
|
|
}
|
|
|
|
|
|
#ifndef UA_ENABLE_MULTITHREADING
|
|
|
- /* Process delayed callbacks when all callbacks and
|
|
|
- * network events are done */
|
|
|
- processDelayedCallbacks(server);
|
|
|
+ /* Process delayed callbacks when all callbacks and network events are done.
|
|
|
+ * If multithreading is enabled, the cleanup of delayed values is attempted
|
|
|
+ * by a callback in the job queue. */
|
|
|
+ UA_Server_cleanupDelayedCallbacks(server);
|
|
|
#endif
|
|
|
|
|
|
#if defined(UA_ENABLE_DISCOVERY_MULTICAST) && !defined(UA_ENABLE_MULTITHREADING)
|
|
@@ -394,10 +410,7 @@ UA_Server_run_shutdown(UA_Server *server) {
|
|
|
nl->stop(nl, server);
|
|
|
}
|
|
|
|
|
|
-#ifndef UA_ENABLE_MULTITHREADING
|
|
|
- /* Process remaining delayed callbacks */
|
|
|
- processDelayedCallbacks(server);
|
|
|
-#else
|
|
|
+#ifdef UA_ENABLE_MULTITHREADING
|
|
|
/* Shut down the workers */
|
|
|
if(server->workers) {
|
|
|
UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
|
|
@@ -412,13 +425,16 @@ UA_Server_run_shutdown(UA_Server *server) {
|
|
|
server->workers = NULL;
|
|
|
}
|
|
|
|
|
|
- /* Execute the remaining callbacks in the dispatch queue.
|
|
|
- * This also executes the delayed callbacks. */
|
|
|
- emptyDispatchQueue(server);
|
|
|
+ /* Execute the remaining callbacks in the dispatch queue. Also executes
|
|
|
+ * delayed callbacks. */
|
|
|
+ UA_Server_cleanupDispatchQueue(server);
|
|
|
+#else
|
|
|
+ /* Process remaining delayed callbacks */
|
|
|
+ UA_Server_cleanupDelayedCallbacks(server);
|
|
|
#endif
|
|
|
|
|
|
- /* Stop multicast discovery */
|
|
|
#ifdef UA_ENABLE_DISCOVERY_MULTICAST
|
|
|
+ /* Stop multicast discovery */
|
|
|
if(server->config.applicationDescription.applicationType ==
|
|
|
UA_APPLICATIONTYPE_DISCOVERYSERVER)
|
|
|
stopMulticastDiscoveryServer(server);
|