Browse Source

Merge pull request #46 from jpfr/master

./configure --enable-multithreading=yes -> MT-Flag
Sten 11 years ago
parent
commit
33d0c38cc7
6 changed files with 59 additions and 24 deletions
  1. 16 7
      configure.ac
  2. 6 1
      examples/src/Makefile.am
  3. 4 0
      examples/src/networklayer.c
  4. 2 0
      examples/src/networklayer.h
  5. 20 10
      src/ua_namespace.c
  6. 11 6
      src/ua_namespace.h

+ 16 - 7
configure.ac

@@ -32,17 +32,26 @@ AM_COND_IF([TARGET_LINUX],
 AC_ARG_ENABLE(debug,
 AS_HELP_STRING([--enable-debug],
                [enable debugging, default: no]),
-[case "${enableval}" in
-             yes) debug=true ;;
-             no)  debug=false ;;
-             *)   AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;;
-esac],
-[debug=false])
-
+			   [case "${enableval}" in
+               		 yes) debug=true ;;
+             		 no)  debug=false ;;
+             		 *)   AC_MSG_ERROR([bad value ${enableval} for --enable-debug]) ;; esac],
+				[debug=false])
 AM_CONDITIONAL(DEBUG, test x"$debug" = x"true")
 AM_COND_IF([DEBUG],
     AC_DEFINE([DEBUG])) #define DEBUG is accessible from pre-processor
 
+AC_ARG_ENABLE(multithreading,
+AS_HELP_STRING([--enable-multithreading],
+               [enable debugging, default: yes]),
+			   [case "${enableval}" in
+               		 yes) multithreading=true ;;
+             		 no)  multithreading=false ;;
+             		 *)   AC_MSG_ERROR([bad value ${enableval} for --enable-multithreading]) ;; esac],
+[multithreading=true])
+AM_CONDITIONAL(MULTITHREADING, test x"$multithreading" = x"true")
+AM_COND_IF([MULTITHREADING],
+    AC_DEFINE([MULTITHREADING])) #define MULTITHREADING is accessible from pre-processor
    
 AC_LIBTOOL_WIN32_DLL
 AC_PROG_LIBTOOL

+ 6 - 1
examples/src/Makefile.am

@@ -7,7 +7,12 @@ __top_builddir__bin_exampleServer_LDADD= $(top_builddir)/lib/libopen62541.a
 
 __top_builddir__bin_exampleServerMT_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include
 __top_builddir__bin_exampleServerMT_SOURCES = opcuaServerMT.c networklayer.c
-__top_builddir__bin_exampleServerMT_LDADD= $(top_builddir)/lib/libopen62541.a -lpthread
+if MULTITHREADING
+MT_LDADD = -lpthread
+else
+MT_LDADD =
+endif
+__top_builddir__bin_exampleServerMT_LDADD= $(top_builddir)/lib/libopen62541.a $(MT_LDADD)
 
 __top_builddir__bin_exampleServerACPLT_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include
 __top_builddir__bin_exampleServerACPLT_SOURCES = opcuaServerACPLT.c 

+ 4 - 0
examples/src/networklayer.c

@@ -161,7 +161,9 @@ void* NL_TCP_listen(NL_connection* c) {
 				UA_list_addPayloadToBack(&(tld->connections),cclient);
 				if (tld->threaded == NL_THREADINGTYPE_PTHREAD) {
 					// TODO: handle retval of pthread_create
+#ifdef MULTITHREADING
 					pthread_create( &(cclient->readerThreadHandle), NULL, (void*(*)(void*)) NL_TCP_reader, (void*) cclient);
+#endif
 				} else {
 					NL_TCP_SetNonBlocking(cclient->connection.connectionHandle);
 				}
@@ -271,7 +273,9 @@ UA_Int32 NL_TCP_init(NL_data* tld, UA_Int32 port) {
 		UA_list_addPayloadToBack(&(tld->connections),c);
 		if (tld->threaded == NL_THREADINGTYPE_PTHREAD) {
 			// TODO: handle retval of pthread_create
+#ifdef MULTITHREADING
 			pthread_create( &(c->readerThreadHandle), NULL, (void*(*)(void*)) NL_TCP_listen, (void*) c);
+#endif
 		} else {
 			NL_TCP_SetNonBlocking(c->connection.connectionHandle);
 		}

+ 2 - 0
examples/src/networklayer.h

@@ -13,7 +13,9 @@
 #include "ua_transportLayer.h"
 #include "ua_list.h"
 
+#ifdef MULTITHREADING
 #include <pthread.h> // pthreadcreate, pthread_t
+#endif
 #include <sys/select.h> // FD_ZERO, FD_SET
 
 #define NL_MAXCONNECTIONS_DEFAULT 10

+ 20 - 10
src/ua_namespace.c

@@ -104,9 +104,11 @@ UA_Int32 insert_node(namespace *ns, UA_Node *node) {
 		
 	hash_t h = hash(&node->nodeId);
 	ns_entry *slot = find_empty_slot(ns, h);
+#ifdef MULTITHREADING
 	if (UA_alloc((void *)&slot->lock, sizeof(pthread_rwlock_t)) != UA_SUCCESS)
 		return UA_ERR_NO_MEMORY;
 	pthread_rwlock_init((pthread_rwlock_t *)slot->lock, NULL);
+#endif
 	slot->node = node;
 	return UA_SUCCESS;
 }
@@ -114,57 +116,61 @@ UA_Int32 insert_node(namespace *ns, UA_Node *node) {
 UA_Int32 get_node(namespace *ns, UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock) {
 	ns_entry *slot;
 	if(find_slot(ns, &slot, nodeid) == UA_SUCCESS) return UA_ERROR;
+#ifdef MULTITHREADING
 	if(pthread_rwlock_rdlock((pthread_rwlock_t *)slot->lock) != 0) return UA_ERROR;
-	*result = slot->node;
 	*lock = slot->lock;
+#endif
+	*result = slot->node;
 	return UA_SUCCESS;
 }
 
 UA_Int32 get_writable_node(namespace *ns, UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock) {
 	ns_entry *slot;
 	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
+#ifdef MULTITHREADING
 	if(pthread_rwlock_wrlock((pthread_rwlock_t *)slot->lock) != 0) return UA_ERROR;
-	*result = slot->node;
 	*lock = slot->lock;
+#endif
+	*result = slot->node;
 	return UA_SUCCESS;
 }
 
+#ifdef MULTITHREADING
 static inline void release_context_walker(void * lock) { pthread_rwlock_unlock(lock); }
+#endif
 
 UA_Int32 get_tc_node(namespace *ns, transaction_context *tc, UA_NodeId *nodeid, UA_Node ** const result, ns_lock ** lock) {
 	ns_entry *slot;
 	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
+#ifdef MULTITHREADING
 	if(pthread_rwlock_tryrdlock((pthread_rwlock_t *)slot->lock) != 0) {
 		/* Transaction failed. Release all acquired locks and bail out. */
 		UA_list_destroy((UA_list_List*) tc, release_context_walker);
 		return UA_ERROR;
 	}
-
 	UA_list_addPayloadToBack((UA_list_List*) tc, slot->lock);
-	*result = slot->node;
 	*lock = slot->lock;
+#endif
+	*result = slot->node;
 	return UA_SUCCESS;
 }
 
 UA_Int32 get_tc_writable_node(namespace *ns, transaction_context *tc, UA_NodeId *nodeid, UA_Node **result, ns_lock ** lock) {
 	ns_entry *slot;
 	if(find_slot(ns, &slot, nodeid) != UA_SUCCESS) return UA_ERROR;
+#ifdef MULTITHREADING
 	if(pthread_rwlock_trywrlock((pthread_rwlock_t *)slot->lock) != 0) {
 		/* Transaction failed. Release all acquired locks and bail out. */
 		UA_list_destroy((UA_list_List*) tc, release_context_walker);
 		return UA_ERROR;
 	}
-
 	UA_list_addPayloadToBack((UA_list_List*) tc, slot->lock);
-	*result = slot->node;
 	*lock = slot->lock;
+#endif
+	*result = slot->node;
 	return UA_SUCCESS;
 }
 
-//inline void release_node(ns_lock *lock) {
-//	pthread_rwlock_unlock((pthread_rwlock_t *)lock);
-//}
-
 void delete_node(namespace *ns, UA_NodeId *nodeid) {
 	ns_entry *slot;
 	if (find_slot(ns, &slot, nodeid) != UA_SUCCESS)
@@ -303,7 +309,9 @@ static inline void clear_slot(namespace *ns, ns_entry *slot) {
 	if(slot->node == UA_NULL)
 		return;
 	
+#ifdef MULTITHREADING
 	pthread_rwlock_wrlock((pthread_rwlock_t *) slot->lock); /* Get write lock. */
+#endif
 	switch(slot->node->nodeClass) {
 	case UA_NODECLASS_OBJECT:
 		UA_ObjectNode_delete((UA_ObjectNode *) slot->node);
@@ -333,8 +341,10 @@ static inline void clear_slot(namespace *ns, ns_entry *slot) {
 		break;
 	}
 	slot->node = UA_NULL;
+#ifdef MULTITHREADING
 	pthread_rwlock_destroy((pthread_rwlock_t *)slot->lock);
 	UA_free(slot->lock);
+#endif
 }
 
 /* Delete all entries */

+ 11 - 6
src/ua_namespace.h

@@ -1,17 +1,18 @@
 #ifndef __NAMESPACE_H__
 #define __NAMESPACE_H__
 
-/* Defines needed for pthread_rwlock_t */
-#define _XOPEN_SOURCE 500
-// this one is necessary on my 3.0.0-32-generic machine
-#define __USE_UNIX98
-#include <pthread.h>
-
 #include "ua_basictypes.h"
 #include "opcua.h"
 #include "ua_list.h"
 
+#ifdef MULTITHREADING
+#define _XOPEN_SOURCE 500
+#define __USE_UNIX98
+#include <pthread.h>
 typedef struct pthread_rwlock_t ns_lock;
+#else
+typedef void ns_lock;
+#endif
 
 /* Poor-man's transactions: If we need multiple locks and at least one of them
    is a writelock ("transaction"), a deadlock can be introduced in conjunction
@@ -31,7 +32,9 @@ UA_Int32 init_tc(transaction_context * tc);
 /* Each namespace is a hash-map of NodeIds to Nodes. Every entry in the hashmap
    consists of a pointer to a read-write lock and a pointer to the Node. */
 typedef struct ns_entry_t {
+#ifdef MULTITHREADING
 	ns_lock *lock; /* locks are heap-allocated, so we can resize the entry-array online */
+#endif
 	UA_Node *node;
 } ns_entry;
 
@@ -56,7 +59,9 @@ UA_Int32 get_tc_writable_node(namespace *ns, transaction_context *tc, UA_NodeId
 // inline void release_node(ns_lock *lock);
 // portable solution, see http://www.greenend.org.uk/rjk/tech/inline.html
 static inline void release_node(ns_lock *lock) {
+#ifdef MULTITHREADING
 	pthread_rwlock_unlock((pthread_rwlock_t *)lock);
+#endif
 }
 void delete_node(namespace *ns, UA_NodeId *nodeid);