celix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pnol...@apache.org
Subject [1/2] celix git commit: CELIX-272: Added locking/threading example to test synchronization solutions and isues. Introduced release/retain concept for service reference and service registration.
Date Mon, 09 Nov 2015 17:07:55 GMT
Repository: celix
Updated Branches:
  refs/heads/feature/CELIX-272_synchronization_service_registry [created] e0231e51e


http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/src/service_registration.c
----------------------------------------------------------------------
diff --git a/framework/private/src/service_registration.c b/framework/private/src/service_registration.c
index 1817784..718a633 100644
--- a/framework/private/src/service_registration.c
+++ b/framework/private/src/service_registration.c
@@ -26,6 +26,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <assert.h>
 
 #include "service_registration_private.h"
 #include "constants.h"
@@ -35,9 +36,9 @@
 #include "celix_threads.h"
 
 static celix_status_t serviceRegistration_initializeProperties(service_registration_pt registration,
properties_pt properties);
-
-celix_status_t serviceRegistration_createInternal(service_registry_pt registry, bundle_pt
bundle, char * serviceName, long serviceId,
+static celix_status_t serviceRegistration_createInternal(service_registry_pt registry, bundle_pt
bundle, char * serviceName, long serviceId,
         void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt
*registration);
+static celix_status_t serviceRegistration_destroy(service_registration_pt registration);
 
 service_registration_pt serviceRegistration_create(service_registry_pt registry, bundle_pt
bundle, char * serviceName, long serviceId, void * serviceObject, properties_pt dictionary)
{
     service_registration_pt registration = NULL;
@@ -51,39 +52,61 @@ service_registration_pt serviceRegistration_createServiceFactory(service_registr
     return registration;
 }
 
-celix_status_t serviceRegistration_createInternal(service_registry_pt registry, bundle_pt
bundle, char * serviceName, long serviceId,
-        void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt
*registration) {
+static celix_status_t serviceRegistration_createInternal(service_registry_pt registry, bundle_pt
bundle, char * serviceName, long serviceId,
+        void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt
*out) {
     celix_status_t status = CELIX_SUCCESS;
 
-    *registration = malloc(sizeof(**registration));
-    if (*registration) {
-        (*registration)->services = NULL;
-        (*registration)->nrOfServices = 0;
-		(*registration)->isServiceFactory = isFactory;
-		(*registration)->registry = registry;
-		(*registration)->className = strdup(serviceName);
-		(*registration)->bundle = bundle;
-
-		(*registration)->serviceId = serviceId;
-		(*registration)->svcObj = serviceObject;
+	service_registration_pt  reg = calloc(1, sizeof(*reg));
+    if (reg) {
+        reg->services = NULL;
+        reg->nrOfServices = 0;
+		reg->isServiceFactory = isFactory;
+		reg->registry = registry;
+		reg->className = strdup(serviceName);
+		reg->bundle = bundle;
+		reg->refCount = 1;
+
+		reg->serviceId = serviceId;
+		reg->svcObj = serviceObject;
 		if (isFactory) {
-			(*registration)->serviceFactory = (service_factory_pt) (*registration)->svcObj;
+			reg->serviceFactory = (service_factory_pt) reg->svcObj;
 		} else {
-			(*registration)->serviceFactory = NULL;
+			reg->serviceFactory = NULL;
 		}
 
-		(*registration)->isUnregistering = false;
-		celixThreadMutex_create(&(*registration)->mutex, NULL);
+		reg->isUnregistering = false;
+		celixThreadMutex_create(&reg->mutex, NULL);
 
-		serviceRegistration_initializeProperties(*registration, dictionary);
+		serviceRegistration_initializeProperties(reg, dictionary);
     } else {
     	status = CELIX_ENOMEM;
     }
 
+	if (status == CELIX_SUCCESS) {
+		*out = reg;
+	}
+
 	return status;
 }
 
-celix_status_t serviceRegistration_destroy(service_registration_pt registration) {
+void serviceRegistration_retain(service_registration_pt registration) {
+	celixThreadMutex_lock(&registration->mutex);
+	registration->refCount += 1;
+	celixThreadMutex_unlock(&registration->mutex);
+}
+
+void serviceRegistration_release(service_registration_pt registration) {
+	celixThreadMutex_lock(&registration->mutex);
+	assert(registration->refCount > 0);
+	registration->refCount -= 1;
+	if (registration->refCount == 0) {
+		serviceRegistration_destroy(registration);
+	} else {
+		celixThreadMutex_unlock(&registration->mutex);
+	}
+}
+
+static celix_status_t serviceRegistration_destroy(service_registration_pt registration) {
     free(registration->className);
 	registration->className = NULL;
 	registration->registry = NULL;
@@ -99,7 +122,7 @@ celix_status_t serviceRegistration_destroy(service_registration_pt registration)
 }
 
 static celix_status_t serviceRegistration_initializeProperties(service_registration_pt registration,
properties_pt dictionary) {
-	char * sId = (char *)malloc(sizeof(registration->serviceId) + 1);
+    char sId[32];
 
 	if (dictionary == NULL) {
 		dictionary = properties_create();
@@ -107,15 +130,13 @@ static celix_status_t serviceRegistration_initializeProperties(service_registrat
 
 	registration->properties = dictionary;
 
-	sprintf(sId, "%ld", registration->serviceId);
+	snprintf(sId, 32, "%ld", registration->serviceId);
 	properties_set(dictionary, (char *) OSGI_FRAMEWORK_SERVICE_ID, sId);
 
 	if (properties_get(dictionary, (char *) OSGI_FRAMEWORK_OBJECTCLASS) == NULL) {
 		properties_set(dictionary, (char *) OSGI_FRAMEWORK_OBJECTCLASS, registration->className);
 	}
 
-	free(sId);
-
 	return CELIX_SUCCESS;
 }
 

http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/src/service_registry.c
----------------------------------------------------------------------
diff --git a/framework/private/src/service_registry.c b/framework/private/src/service_registry.c
index f9cea4e..ec72f6d 100644
--- a/framework/private/src/service_registry.c
+++ b/framework/private/src/service_registry.c
@@ -38,7 +38,9 @@
 #include "celix_log.h"
 
 static celix_status_t serviceRegistry_getUsageCount(service_registry_pt registry, bundle_pt
bundle, service_reference_pt reference, usage_count_pt *usageCount);
-static celix_status_t serviceRegistry_addUsageCount(service_registry_pt registry, bundle_pt
bundle, service_reference_pt reference, usage_count_pt *usageCount);
+static celix_status_t serviceRegistry_addUsageCount(service_registry_pt registry, bundle_pt
bundle,
+                                                   service_reference_pt reference,
+                                                   service_registration_pt registration,
usage_count_pt *usageCount);
 static celix_status_t serviceRegistry_flushUsageCount(service_registry_pt registry, bundle_pt
bundle, service_reference_pt reference);
 
 celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt
bundle, char * serviceName, void * serviceObject, properties_pt dictionary, bool isFactory,
service_registration_pt *registration);
@@ -108,12 +110,17 @@ static celix_status_t serviceRegistry_getUsageCount(service_registry_pt
registry
 	return CELIX_SUCCESS;
 }
 
-static celix_status_t serviceRegistry_addUsageCount(service_registry_pt registry, bundle_pt
bundle, service_reference_pt reference, usage_count_pt *usageCount) {
+static celix_status_t serviceRegistry_addUsageCount(service_registry_pt registry, bundle_pt
bundle,
+                                                   service_reference_pt reference,
+                                                   service_registration_pt registration,
usage_count_pt *usageCount) {
 	array_list_pt usages = hashMap_get(registry->inUseMap, bundle);
 	usage_count_pt usage = malloc(sizeof(*usage));
 	usage->reference = reference;
 	usage->count = 0;
 	usage->service = NULL;
+    usage->registration = registration;
+
+    serviceRegistration_retain(registration);
 
 	if (usages == NULL) {
 		arrayList_create(&usages);
@@ -134,6 +141,7 @@ static celix_status_t serviceRegistry_flushUsageCount(service_registry_pt
regist
 			serviceReference_equals(usage->reference, reference, &equals);
 			if (equals) {
 				arrayListIterator_remove(iter);
+                serviceRegistration_release(usage->registration);
 				free(usage);
 			}
 		}
@@ -262,10 +270,8 @@ celix_status_t serviceRegistry_unregisterService(service_registry_pt
registry, b
 	}
 	arrayList_destroy(references);
 
-	//TODO not needed, the registration is destroyed, any reference to the registration is invalid
and will result in a segfault
-	serviceRegistration_invalidate(registration);
-
-	// serviceRegistration_destroy(registration);
+    serviceRegistration_invalidate(registration);
+    serviceRegistration_release(registration);
 
 	celixThreadMutex_unlock(&registry->mutex);
 
@@ -345,7 +351,7 @@ celix_status_t serviceRegistry_getServiceReferencesForRegistration(service_regis
             service_registration_pt reg = NULL;
             service_reference_pt reference = (service_reference_pt) arrayList_get(refs, refIdx);
             bool valid = false;
-            serviceRefernce_isValid(reference, &valid);
+			serviceReference_isValid(reference, &valid);
             if (valid) {
                 serviceReference_getServiceRegistration(reference, &reg);
                 if (reg == registration) {
@@ -421,7 +427,7 @@ celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt
registr
     celix_status_t status = CELIX_SUCCESS;
 
     bool valid = false;
-    serviceRefernce_isValid(reference, &valid);
+	serviceReference_isValid(reference, &valid);
     if (valid) {
         bool ungetResult = true;
         while (ungetResult) {
@@ -433,7 +439,7 @@ celix_status_t serviceRegistry_ungetServiceReference(service_registry_pt
registr
     array_list_pt references = hashMap_get(registry->serviceReferences, owner);
     if (references != NULL) {
         arrayList_removeElement(references, reference);
-        serviceReference_destroy(&reference);
+        serviceReference_release(reference);
         if (arrayList_size(references) > 0) {
             hashMap_put(registry->serviceReferences, owner, references);
         } else {
@@ -494,7 +500,7 @@ celix_status_t serviceRegistry_getService(service_registry_pt registry,
bundle_p
 	if (serviceRegistration_isValid(registration)) {
 		status = serviceRegistry_getUsageCount(registry, bundle, reference, &usage);
 		if (usage == NULL) {
-			status = serviceRegistry_addUsageCount(registry, bundle, reference, &usage);
+			status = serviceRegistry_addUsageCount(registry, bundle, reference, registration, &usage);
 		}
 		usage->count++;
 		*service = usage->service;

http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/public/include/properties.h
----------------------------------------------------------------------
diff --git a/framework/public/include/properties.h b/framework/public/include/properties.h
index c4803cb..9fa5f68 100644
--- a/framework/public/include/properties.h
+++ b/framework/public/include/properties.h
@@ -31,6 +31,7 @@
 
 #include "hash_map.h"
 #include "framework_exports.h"
+#include "celix_errno.h"
 
 typedef hash_map_pt properties_pt;
 
@@ -44,4 +45,6 @@ FRAMEWORK_EXPORT char * properties_get(properties_pt properties, char *
key);
 FRAMEWORK_EXPORT char * properties_getWithDefault(properties_pt properties, char * key, char
* defaultValue);
 FRAMEWORK_EXPORT char * properties_set(properties_pt properties, char * key, char * value);
 
+FRAMEWORK_EXPORT celix_status_t properties_copy(properties_pt properties, properties_pt *copy);
+
 #endif /* PROPERTIES_H_ */


Mime
View raw message