You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2015/11/09 18:07:55 UTC
[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.
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(®->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(®istration->mutex);
+ registration->refCount += 1;
+ celixThreadMutex_unlock(®istration->mutex);
+}
+
+void serviceRegistration_release(service_registration_pt registration) {
+ celixThreadMutex_lock(®istration->mutex);
+ assert(registration->refCount > 0);
+ registration->refCount -= 1;
+ if (registration->refCount == 0) {
+ serviceRegistration_destroy(registration);
+ } else {
+ celixThreadMutex_unlock(®istration->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(®istry->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, ®);
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_ */
[2/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.
Posted by pn...@apache.org.
CELIX-272: Added locking/threading example to test synchronization solutions and isues. Introduced release/retain concept for service reference and service registration.
Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/e0231e51
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/e0231e51
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/e0231e51
Branch: refs/heads/feature/CELIX-272_synchronization_service_registry
Commit: e0231e51e4cac30018c7a71f9469e838348f642b
Parents: e9f2baa
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Mon Nov 9 18:06:18 2015 +0100
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Mon Nov 9 18:06:18 2015 +0100
----------------------------------------------------------------------
.../private/src/dm_component_impl.c | 5 +-
examples/CMakeLists.txt | 1 +
examples/deploy.cmake | 3 +
examples/locking/CMakeLists.txt | 24 ++
examples/locking/benchmark/CMakeLists.txt | 30 ++
.../private/src/benchmark_runner_activator.c | 255 +++++++++++++
.../benchmark/public/include/benchmark.h | 29 ++
.../benchmark/public/include/benchmark_result.h | 20 +
.../public/include/benchmark_service.h | 27 ++
.../public/include/frequency_service.h | 47 +++
.../benchmark/public/include/math_service.h | 40 ++
.../benchmark/public/src/benchmark_activator.c | 133 +++++++
examples/locking/consumer.c | 372 +++++++++++++++++++
examples/locking/math_provider/CMakeLists.txt | 32 ++
.../private/include/math_component.h | 14 +
.../math_provider/private/src/math_component.c | 28 ++
.../private/src/provider_activator.c | 219 +++++++++++
.../modified_bool_benchmark/CMakeLists.txt | 32 ++
.../private/src/modified_bool_benchmark.c | 162 ++++++++
examples/locking/mutex_benchmark/CMakeLists.txt | 32 ++
.../private/src/mutex_benchmark.c | 117 ++++++
.../locking/reference_benchmark/CMakeLists.txt | 32 ++
.../private/src/reference_benchmark.c | 116 ++++++
.../locking/start_stop_benchmark/CMakeLists.txt | 32 ++
.../private/src/start_stop_benchmark.c | 189 ++++++++++
.../private/include/service_reference_private.h | 9 +-
.../include/service_registration_private.h | 6 +-
.../private/include/service_registry_private.h | 1 +
framework/private/src/properties.c | 22 ++
framework/private/src/service_reference.c | 71 ++--
framework/private/src/service_registration.c | 71 ++--
framework/private/src/service_registry.c | 26 +-
framework/public/include/properties.h | 3 +
33 files changed, 2130 insertions(+), 70 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/dependency_manager/private/src/dm_component_impl.c
----------------------------------------------------------------------
diff --git a/dependency_manager/private/src/dm_component_impl.c b/dependency_manager/private/src/dm_component_impl.c
index d08bc28..aa34389 100644
--- a/dependency_manager/private/src/dm_component_impl.c
+++ b/dependency_manager/private/src/dm_component_impl.c
@@ -1097,8 +1097,9 @@ celix_status_t component_registerServices(dm_component_pt component) {
for (i = 0; i < arrayList_size(component->dm_interfaces); i++) {
dm_interface_t *interface = arrayList_get(component->dm_interfaces, i);
-
- bundleContext_registerService(component->context, interface->serviceName, interface->service, interface->properties, &interface->registration);
+ properties_pt regProps = NULL;
+ properties_copy(interface->properties, ®Props);
+ bundleContext_registerService(component->context, interface->serviceName, interface->service, regProps, &interface->registration);
}
}
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 677a6aa..55468a4 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -32,6 +32,7 @@ if (EXAMPLES)
add_subdirectory(osgi-in-action/chapter04-correct-listener)
add_subdirectory(osgi-in-action/chapter01-greeting-example)
#add_subdirectory(osgi-in-action/chapter04-paint-example) chapter4 example is still based on APR
+ add_subdirectory(locking)
#add_subdirectory(embedding) embedding is still baed on APR
endif(EXAMPLES)
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/deploy.cmake
----------------------------------------------------------------------
diff --git a/examples/deploy.cmake b/examples/deploy.cmake
index 24c7a11..234f90b 100644
--- a/examples/deploy.cmake
+++ b/examples/deploy.cmake
@@ -28,4 +28,7 @@ if (EXAMPLES)
if (NOT ANDROID)
deploy("mongoose" BUNDLES shell shell_tui log_service apache_celix_examples_mongoose)
endif ()
+
+ deploy("locking_example" BUNDLES benchmark_runner reference_benchmark start_stop_benchmark mutex_benchmark math_provider shell shell_tui log_service log_writer)
+
endif (EXAMPLES)
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/locking/CMakeLists.txt b/examples/locking/CMakeLists.txt
new file mode 100644
index 0000000..e6c80ab
--- /dev/null
+++ b/examples/locking/CMakeLists.txt
@@ -0,0 +1,24 @@
+ # Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+add_subdirectory(benchmark)
+add_subdirectory(math_provider)
+
+add_subdirectory(mutex_benchmark)
+add_subdirectory(reference_benchmark)
+add_subdirectory(start_stop_benchmark)
+add_subdirectory(modified_bool_benchmark)
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/locking/benchmark/CMakeLists.txt b/examples/locking/benchmark/CMakeLists.txt
new file mode 100644
index 0000000..ce5db7c
--- /dev/null
+++ b/examples/locking/benchmark/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+SET(BUNDLE_SYMBOLICNAME benchmark_runner)
+SET(BUNDLE_VERSION 0.0.0)
+
+bundle(benchmark_runner SOURCES
+ private/src/benchmark_runner_activator
+)
+
+include_directories(private/include)
+include_directories(public/include)
+include_directories(${PROJECT_SOURCE_DIR}/framework/public/include)
+include_directories(${PROJECT_SOURCE_DIR}/utils/public/include)
+
+target_link_libraries(benchmark_runner celix_framework)
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/private/src/benchmark_runner_activator.c
----------------------------------------------------------------------
diff --git a/examples/locking/benchmark/private/src/benchmark_runner_activator.c b/examples/locking/benchmark/private/src/benchmark_runner_activator.c
new file mode 100644
index 0000000..e06b77b
--- /dev/null
+++ b/examples/locking/benchmark/private/src/benchmark_runner_activator.c
@@ -0,0 +1,255 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * benchmark_activator.c
+ *
+ * \date Feb 12, 2014
+ * \author <a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+
+#include <pthread.h>
+
+#include "bundle_activator.h"
+#include "bundle_context.h"
+#include "service_registration.h"
+#include "service_tracker.h"
+
+#include "benchmark_service.h"
+#include "frequency_service.h"
+
+static celix_status_t benchmarkRunner_addingService(void * handle, service_reference_pt reference, void **service);
+static celix_status_t benchmarkRunner_addedService(void * handle, service_reference_pt reference, void * service);
+static celix_status_t benchmarkRunner_modifiedService(void * handle, service_reference_pt reference, void * service);
+static celix_status_t benchmarkRunner_removedService(void * handle, service_reference_pt reference, void * service);
+
+static void benchmarkRunner_runBenchmark(struct activator *activator);
+static void benchmarkRunner_printHeader(char *name, unsigned int nrOfSamples);
+static void benchmarkRunner_printResult(benchmark_result_t result, double updateFreq, unsigned long elapsedTime);
+static void benchmarkRunner_printFooter(char *name);
+
+struct benchmark_entry {
+ benchmark_service_pt benchmark;
+ LIST_ENTRY(benchmark_entry) entries;
+};
+
+struct activator {
+ bundle_context_pt context;
+ service_tracker_customizer_pt customizer;
+ service_tracker_pt tracker;
+ pthread_t thread;
+
+ pthread_mutex_t mutex;
+ array_list_pt benchmarks;
+ LIST_HEAD(benchmark_entries, entries) benchmarkEntries;
+ frequency_service_pt freqService;
+};
+
+celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
+ struct activator * activator = malloc(sizeof(*activator));
+ activator->context=context;
+ activator->customizer = NULL;
+ activator->tracker= NULL;
+ activator->benchmarks = NULL;
+ activator->freqService = NULL;
+
+ LIST_INIT(&activator->benchmarkEntries);
+
+ *userData = activator;
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = userData;
+
+ pthread_mutex_init(&activator->mutex, NULL);
+
+ arrayList_create(&activator->benchmarks);
+
+ serviceTrackerCustomizer_create(activator, benchmarkRunner_addingService, benchmarkRunner_addedService, benchmarkRunner_modifiedService, benchmarkRunner_removedService, &activator->customizer);
+
+ char filter[128];
+ sprintf(filter, "(|(%s=%s)(%s=%s))", "objectClass", BENCHMARK_SERVICE_NAME, "objectClass", FREQUENCY_SERVICE_NAME);
+ serviceTracker_createWithFilter(context, filter, activator->customizer, &activator->tracker);
+ serviceTracker_open(activator->tracker);
+
+ pthread_create(&activator->thread, NULL, (void *)benchmarkRunner_runBenchmark, activator);
+
+ return status;
+}
+
+
+celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
+ struct activator * activator = userData;
+
+ pthread_join(activator->thread, NULL);
+
+ serviceTracker_close(activator->tracker);
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
+ struct activator * activator = userData;
+
+ return CELIX_SUCCESS;
+}
+
+static celix_status_t benchmarkRunner_addingService(void * handle, service_reference_pt reference, void **service) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = handle;
+ status = bundleContext_getService(activator->context, reference, service);
+ return status;
+
+}
+static celix_status_t benchmarkRunner_addedService(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = handle;
+
+ service_registration_pt registration = NULL;
+ properties_pt properties = NULL;
+ char *serviceName = NULL;
+ serviceReference_getServiceRegistration(reference, ®istration);
+ serviceRegistration_getProperties(registration, &properties);
+ serviceName = properties_get(properties, "objectClass");
+ if (strcmp(serviceName, BENCHMARK_SERVICE_NAME) == 0) {
+ pthread_mutex_lock(&activator->mutex);
+ arrayList_add(activator->benchmarks, service);
+ pthread_mutex_unlock(&activator->mutex);
+ } else if (strcmp(serviceName, FREQUENCY_SERVICE_NAME) == 0 ) {
+ pthread_mutex_lock(&activator->mutex);
+ activator->freqService = service;
+ pthread_mutex_unlock(&activator->mutex);
+ }
+
+ return status;
+}
+static celix_status_t benchmarkRunner_modifiedService(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = handle;
+ return status;
+}
+
+static celix_status_t benchmarkRunner_removedService(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = handle;
+
+ service_registration_pt registration = NULL;
+ properties_pt properties = NULL;
+ char *serviceName = NULL;
+ serviceReference_getServiceRegistration(reference, ®istration);
+ serviceRegistration_getProperties(registration, &properties);
+ serviceName = properties_get(properties, "objectClass");
+ if (strcmp(serviceName, BENCHMARK_SERVICE_NAME) == 0) {
+ pthread_mutex_lock(&activator->mutex);
+ arrayList_removeElement(activator->benchmarks, service);
+ pthread_mutex_unlock(&activator->mutex);
+ } else if (strcmp(serviceName, FREQUENCY_SERVICE_NAME) == 0 ) {
+ pthread_mutex_lock(&activator->mutex);
+ if (activator->freqService == service) {
+ activator->freqService = NULL;
+ }
+ pthread_mutex_unlock(&activator->mutex);
+ }
+
+ return status;
+}
+
+static void benchmarkRunner_runBenchmark(struct activator *activator) {
+ int i, k;
+ int nrOfBenchmarks;
+ double updateFrequency, measuredFrequency;
+ unsigned int measuredUpdateCounter, nrOfUpdateThreads;
+ int nrOfSamples;
+ benchmark_service_pt benchmarkServ;
+ char *name;
+ benchmark_result_t result;
+ struct timeval begin,end;
+ unsigned long elapsedTime;
+ double sampleFactor;
+
+ int nrOfThreadRuns = 12;
+ int threads[] = {1,2,3,4,5,6,7,8,16,32,64,128};
+
+ nrOfSamples = 100 * 1000;
+ updateFrequency = 1000;
+ nrOfUpdateThreads = 100;
+
+ usleep(2000 * 1000); //wait 2 seconds to get needed services
+
+ pthread_mutex_lock(&activator->mutex);
+ if (activator->freqService != NULL) {
+ activator->freqService->setFrequency(activator->freqService->handle, updateFrequency);
+ activator->freqService->setNrOfThreads(activator->freqService->handle, nrOfUpdateThreads);
+ }
+ nrOfBenchmarks = arrayList_size(activator->benchmarks);
+ for (i = 0 ; i < nrOfBenchmarks ; i += 1) {
+ benchmarkServ = arrayList_get(activator->benchmarks, i);
+ name = benchmarkServ->name(benchmarkServ->handler);
+ sampleFactor = benchmarkServ->getSampleFactor(benchmarkServ->handler);
+ activator->freqService->setBenchmarkName(activator->freqService->handle, name);
+ usleep(1000);
+ benchmarkRunner_printHeader(name, nrOfSamples * sampleFactor);
+ for (k = 0 ; k < nrOfThreadRuns ; k +=1) {
+ if (activator->freqService != NULL) {
+ activator->freqService->resetCounter(activator->freqService->handle);
+
+ }
+ gettimeofday(&begin, NULL);
+ result = benchmarkServ->run(benchmarkServ->handler, threads[k], nrOfSamples * sampleFactor);
+ gettimeofday(&end, NULL);
+ elapsedTime = ((end.tv_sec - begin.tv_sec) * 1000000) + (end.tv_usec - begin.tv_usec);
+ if (activator->freqService != NULL) {
+ measuredUpdateCounter = activator->freqService->getCounter(activator->freqService->handle);
+ measuredFrequency = ((double)(measuredUpdateCounter) / elapsedTime * 1000000);
+ }
+ benchmarkRunner_printResult(result, measuredFrequency, elapsedTime);
+ }
+ benchmarkRunner_printFooter(name);
+ }
+ pthread_mutex_unlock(&activator->mutex);
+}
+
+static void benchmarkRunner_printHeader(char *name, unsigned int nrOfSamples) {
+ int i;
+ printf("---% 35s---------------------------------------------------------------------------------------\n", name);
+ printf("-------samples: %10i---------------------------------------------------------------------------------------------------\n", nrOfSamples);
+}
+
+static void benchmarkRunner_printResult(benchmark_result_t result, double updateFreq, unsigned long elapsedTime) {
+ printf("| threads %5i | ", result.nrOfThreads);
+ printf("average call time: % 10.2f nanoseconds | ", result.averageCallTimeInNanoseconds);
+ printf("frequency calls is % 10.5f MHz | ", result.callFrequencyInMhz);
+ printf("update freq ~ % 8.2f Hz | ", updateFreq);
+ printf("elapsed time is % 8.5f seconds | ", ((double)elapsedTime) / 1000000);
+ printf("\n");
+}
+
+static void benchmarkRunner_printFooter(char *name) {
+ printf("-----------------------------------------------------------------------------------------------------------------------------\n\n\n");
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/include/benchmark.h
----------------------------------------------------------------------
diff --git a/examples/locking/benchmark/public/include/benchmark.h b/examples/locking/benchmark/public/include/benchmark.h
new file mode 100644
index 0000000..971f111
--- /dev/null
+++ b/examples/locking/benchmark/public/include/benchmark.h
@@ -0,0 +1,29 @@
+/*
+ * consumer.h
+ *
+ * Created on: Feb 13, 2014
+ * Author: dl436
+ */
+
+#ifndef CONSUMER_H_
+#define CONSUMER_H_
+
+#include "celix_errno.h"
+
+#include "benchmark_result.h"
+#include "math_service.h"
+
+typedef struct benchmark *benchmark_pt; //ADT
+
+celix_status_t benchmark_create(benchmark_pt *benchmark);
+celix_status_t benchmark_destroy(benchmark_pt benchmark);
+
+benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples);
+char * benchmark_getName(benchmark_pt benchmark);
+double benchmark_getSampleFactor(benchmark_pt benchmark);
+
+celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService);
+celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService);
+
+
+#endif /* CONSUMER_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/include/benchmark_result.h
----------------------------------------------------------------------
diff --git a/examples/locking/benchmark/public/include/benchmark_result.h b/examples/locking/benchmark/public/include/benchmark_result.h
new file mode 100644
index 0000000..e0750a8
--- /dev/null
+++ b/examples/locking/benchmark/public/include/benchmark_result.h
@@ -0,0 +1,20 @@
+/*
+ * benchmark_result.h
+ *
+ * Created on: Feb 13, 2014
+ * Author: dl436
+ */
+
+#ifndef BENCHMARK_RESULT_H_
+#define BENCHMARK_RESULT_H_
+
+typedef struct benchmark_result {
+ unsigned int nrOfThreads;
+ unsigned int nrOfsamples;
+ unsigned int result;
+ unsigned int skips;
+ double averageCallTimeInNanoseconds;
+ double callFrequencyInMhz;
+} benchmark_result_t;
+
+#endif /* BENCHMARK_RESULT_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/include/benchmark_service.h
----------------------------------------------------------------------
diff --git a/examples/locking/benchmark/public/include/benchmark_service.h b/examples/locking/benchmark/public/include/benchmark_service.h
new file mode 100644
index 0000000..63ada04
--- /dev/null
+++ b/examples/locking/benchmark/public/include/benchmark_service.h
@@ -0,0 +1,27 @@
+/*
+ * benchmark_service.h
+ *
+ * Created on: Feb 13, 2014
+ * Author: dl436
+ */
+
+#ifndef BENCHMARK_SERVICE_H_
+#define BENCHMARK_SERVICE_H_
+
+#include "benchmark_result.h"
+
+typedef struct benchmark_service *benchmark_service_pt;
+
+typedef struct benchmark_handler *benchmark_handler_pt; //ADT
+
+#define BENCHMARK_SERVICE_NAME "benchmark_service"
+
+struct benchmark_service {
+ benchmark_handler_pt handler;
+
+ benchmark_result_t (*run)(benchmark_handler_pt handler, int nrOfThreads, int nrOfSamples);
+ char * (*name)(benchmark_handler_pt handler);
+ double (*getSampleFactor)(benchmark_handler_pt benchmark);
+};
+
+#endif /* BENCHMARK_SERVICE_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/include/frequency_service.h
----------------------------------------------------------------------
diff --git a/examples/locking/benchmark/public/include/frequency_service.h b/examples/locking/benchmark/public/include/frequency_service.h
new file mode 100644
index 0000000..5c022ce
--- /dev/null
+++ b/examples/locking/benchmark/public/include/frequency_service.h
@@ -0,0 +1,47 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * frequence_service.h
+ *
+ * \date Feb 4, 2014
+ * \author <a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+//TODO change to math provider service ???
+
+#ifndef FREQUENCY_SERVICE_H
+#define FREQUENCY_SERVICE_H
+
+#define FREQUENCY_SERVICE_NAME "frequency_service"
+
+typedef struct frequency_hander frequence_handler_t;
+
+struct frequency_service {
+ frequence_handler_t *handle;
+ void (*setFrequency)(frequence_handler_t *handle, int freq);
+ void (*resetCounter)(frequence_handler_t *handle);
+ uint (*getCounter)(frequence_handler_t *handle);
+ void (*setBenchmarkName)(frequence_handler_t *handle, char *name);
+ void (*setNrOfThreads)(frequence_handler_t *handle, uint nrOfThreads);
+};
+
+typedef struct frequency_service * frequency_service_pt;
+
+#endif /* FREQUENCY_SERVICE_H */
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/include/math_service.h
----------------------------------------------------------------------
diff --git a/examples/locking/benchmark/public/include/math_service.h b/examples/locking/benchmark/public/include/math_service.h
new file mode 100644
index 0000000..154cc9c
--- /dev/null
+++ b/examples/locking/benchmark/public/include/math_service.h
@@ -0,0 +1,40 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * echo_server.h
+ *
+ * \date Sep 21, 2010
+ * \author <a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+#ifndef MATH_SERVICE_H
+#define MATH_SERVICE_H
+
+#define MATH_SERVICE_NAME "math_service"
+
+
+struct math_service {
+ void *handle;
+ int (*calc)(void *handle, int arg1, int arg2);
+};
+
+typedef struct math_service * math_service_pt;
+
+#endif /* MATH_SERVICE_H */
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/benchmark/public/src/benchmark_activator.c
----------------------------------------------------------------------
diff --git a/examples/locking/benchmark/public/src/benchmark_activator.c b/examples/locking/benchmark/public/src/benchmark_activator.c
new file mode 100644
index 0000000..a161f11
--- /dev/null
+++ b/examples/locking/benchmark/public/src/benchmark_activator.c
@@ -0,0 +1,133 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * echo_server_activator.c
+ *
+ * \date Sep 21, 2010
+ * \author <a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "bundle_activator.h"
+#include "bundle_context.h"
+#include "service_registration.h"
+#include "service_tracker.h"
+
+#include "math_service.h"
+#include "benchmark.h"
+#include "benchmark_service.h"
+#include "frequency_service.h"
+
+static celix_status_t addingService(void * handle, service_reference_pt reference, void **service);
+static celix_status_t addedService(void * handle, service_reference_pt reference, void * service);
+static celix_status_t modifiedService(void * handle, service_reference_pt reference, void * service);
+static celix_status_t removedService(void * handle, service_reference_pt reference, void * service);
+
+struct activator {
+ bundle_context_pt context;
+ benchmark_pt benchmark;
+ benchmark_service_pt mathService;
+ service_tracker_customizer_pt customizer;
+ service_tracker_pt tracker;
+ service_registration_pt registration;
+};
+
+celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
+ struct activator * activator = malloc(sizeof(*activator));
+ activator->context=context;
+ activator->benchmark=NULL;
+ activator->mathService = NULL;
+ activator->customizer = NULL;
+ activator->tracker=NULL;
+ activator->registration = NULL;
+
+ *userData = activator;
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = userData;
+
+ status = benchmark_create(&activator->benchmark);
+ serviceTrackerCustomizer_create(activator, addingService, addedService, modifiedService, removedService, &activator->customizer);
+
+ char filter[128];
+ sprintf(filter, "(&(objectClass=%s)(benchmark=%s))", MATH_SERVICE_NAME, benchmark_getName(activator->benchmark));
+
+ serviceTracker_createWithFilter(context, filter, activator->customizer, &activator->tracker);
+ serviceTracker_open(activator->tracker);
+
+ activator->mathService = malloc(sizeof(*activator->mathService));
+ activator->mathService->handler = (void *)activator->benchmark;
+ activator->mathService->name=(void *)benchmark_getName;
+ activator->mathService->getSampleFactor=(void *)benchmark_getSampleFactor;
+ activator->mathService->run=(void *)benchmark_run;
+
+ status = bundleContext_registerService(activator->context, BENCHMARK_SERVICE_NAME, activator->mathService, NULL, &activator->registration);
+
+ return status;
+}
+
+
+celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
+ struct activator * activator = userData;
+
+ serviceTracker_close(activator->tracker);
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
+ struct activator * activator = userData;
+
+ benchmark_destroy(activator->benchmark);
+ activator->benchmark=NULL;
+
+ return CELIX_SUCCESS;
+}
+
+static celix_status_t addingService(void * handle, service_reference_pt reference, void **service) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = handle;
+ status = bundleContext_getService(activator->context, reference, service);
+ return status;
+
+}
+static celix_status_t addedService(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = handle;
+ benchmark_addMathService(activator->benchmark, service);
+ return status;
+}
+static celix_status_t modifiedService(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = handle;
+ return status;
+}
+
+static celix_status_t removedService(void * handle, service_reference_pt reference, void * service) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = handle;
+ benchmark_removeMathService(activator->benchmark, service);
+ return status;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/consumer.c
----------------------------------------------------------------------
diff --git a/examples/locking/consumer.c b/examples/locking/consumer.c
new file mode 100644
index 0000000..b73549e
--- /dev/null
+++ b/examples/locking/consumer.c
@@ -0,0 +1,372 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * consumer.c
+ *
+ * \date Feb 3, 2014
+ * \author <a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+
+#include "consumer.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include <urcu.h>
+
+#include "math_service.h"
+#include "frequency_service.h"
+
+#define FREELIST_LENGTH 16
+
+typedef union service_counter service_counter_t;
+
+union service_counter {
+ volatile struct {
+ volatile u_int32_t counter; //TODO FIXME assuming little endian!!
+ volatile u_int32_t position;
+ math_service_pt math; // not accesible by raw
+ } info; //TODO rename data
+ volatile u_int64_t data; //TODO rename raw
+};
+
+struct consumer {
+ math_service_pt math;
+ frequency_service_pt frequencyService;
+ locking_type_t currentLockingType;
+ pthread_mutex_t mutex;
+ pthread_rwlock_t rw_lock;
+ service_counter_t *counters[FREELIST_LENGTH];
+ service_counter_t *current;
+};
+
+typedef struct run_info {
+ consumer_pt consumer;
+ volatile locking_type_t type;
+ int nrOfsamples;
+ int result;
+ uint skips;
+ uint updateCounter;
+ struct timeval begin;
+ struct timeval end;
+} run_info_t;
+
+static void * consumer_reference_run(run_info_t *info);
+static void * consumer_no_locking_run(run_info_t *info);
+static void * consumer_mutex_run(run_info_t *info);
+static void * consumer_rcu_run(run_info_t *info);
+static void * consumer_reference_counting_run(run_info_t *info);
+static void * consumer_rw_lock_run(run_info_t *info);
+
+static int consumer_reference_calc(int arg1, int arg2);
+
+celix_status_t consumer_create(consumer_pt *result) {
+ consumer_pt consumer = malloc(sizeof(*consumer));
+ consumer->math = NULL;
+ consumer->frequencyService = NULL;
+ consumer->currentLockingType=LOCKING_TYPE_NO_LOCKING;
+
+
+ service_counter_t *new = malloc(sizeof(service_counter_t));
+ new->info.position = 0;
+ new->info.counter = 0;
+ new->info.math = NULL;
+
+ int i;
+ for (i = 0; i < FREELIST_LENGTH; i+=1) {
+ consumer->counters[i] = NULL;
+ }
+ consumer->current = new;
+ consumer->counters[0] = new;
+
+ pthread_mutex_init(&consumer->mutex, NULL);
+ pthread_rwlock_init(&consumer->rw_lock, NULL);
+
+ rcu_init();
+
+ (*result) = consumer;
+ return CELIX_SUCCESS;
+}
+
+celix_status_t consumer_destroy(consumer_pt consumer) {
+ pthread_mutex_destroy(&consumer->mutex);
+ pthread_rwlock_destroy(&consumer->rw_lock);
+ free(consumer);
+ return CELIX_SUCCESS;
+}
+
+void consumer_setFrequencyService(consumer_pt consumer, frequency_service_pt freqServ) {
+ consumer->frequencyService=freqServ;
+}
+
+void consumer_runBenchmark(consumer_pt consumer, locking_type_t type, int nrOfThreads, int nrOfSamples) {
+ pthread_t threads[nrOfThreads];
+ run_info_t info[nrOfThreads];
+ int elapsedTime, skips, counter;
+ double callTime, callFreq, updateFreq;
+ int i;
+
+ consumer->currentLockingType=type;
+ usleep(1000);
+
+ //init
+ for (i = 0; i< nrOfThreads; i += 1) {
+ info[i].consumer = consumer;
+ info[i].nrOfsamples=nrOfSamples;
+ info[i].result = rand();
+ info[i].skips = 0;
+ info[i].updateCounter = 0;
+ }
+ elapsedTime = 0;
+ skips = 0;
+
+ //start threads
+ info->consumer->frequencyService->resetCounter(info->consumer->frequencyService->handler);
+ for (i = 0; i < nrOfThreads; i += 1) {
+ if (type == LOCKING_TYPE_NO_LOCKING) {
+ pthread_create(&threads[i], NULL, (void *)consumer_no_locking_run, &info[i]);
+ } else if (type == LOCKING_TYPE_MUTEX) {
+ pthread_create(&threads[i], NULL, (void *)consumer_mutex_run, &info[i]);
+ } else if (type == LOCKING_TYPE_REFERENCE) {
+ pthread_create(&threads[i], NULL, (void *)consumer_reference_run, &info[i]);
+ } else if (type == LOCKING_TYPE_RCU) {
+ pthread_create(&threads[i], NULL, (void *)consumer_rcu_run, &info[i]);
+ } else if (type == LOCKING_TYPE_REFERENCE_COUNTER) {
+ pthread_create(&threads[i], NULL, (void *)consumer_reference_counting_run, &info[i]);
+ } else if (type == LOCKING_TYPE_RW_LOCK) {
+ pthread_create(&threads[i], NULL, (void *)consumer_rw_lock_run, &info[i]);
+ } else {
+ printf ("unknown type\n");
+ return;
+ }
+ }
+
+ //join and print result
+
+ for (i = 0; i < nrOfThreads; i +=1 ) {
+ pthread_join(threads[i], NULL);
+ elapsedTime += ((info[i].end.tv_sec - info[i].begin.tv_sec) * 1000000) + (info[i].end.tv_usec - info[i].begin.tv_usec);
+ skips += info[i].skips;
+ counter += info[i].updateCounter;
+ }
+ counter = info->consumer->frequencyService->getCounter(info->consumer->frequencyService->handler);
+ callTime = ((double)elapsedTime * 1000) / (nrOfSamples * nrOfThreads);
+ callFreq = ((double)(nrOfSamples * nrOfThreads) / elapsedTime);
+ updateFreq = ((double)counter * 1000000) / elapsedTime;
+ printf("| threads %5i | ", nrOfThreads);
+ printf("average call time: % 10.2f nanoseconds | ", callTime);
+ printf("frequency calls is % 10.5f MHz | ", callFreq);
+ printf("update freq ~ % 8.2f Hz | ", updateFreq);
+ printf("\n");
+
+ if (skips > 0) {
+ printf("WARNING skips is %i\n", skips);
+ }
+}
+
+celix_status_t consumer_addMathService(consumer_pt consumer, math_service_pt mathService) {
+ if (consumer->currentLockingType == LOCKING_TYPE_MUTEX) {
+ pthread_mutex_lock(&consumer->mutex);
+ consumer->math = mathService;
+ pthread_mutex_unlock(&consumer->mutex);
+ } else if (consumer->currentLockingType == LOCKING_TYPE_RCU) {
+ consumer->math = mathService;
+ synchronize_rcu();
+ } else if (consumer->currentLockingType == LOCKING_TYPE_RW_LOCK) {
+ pthread_rwlock_wrlock(&consumer->rw_lock);
+ consumer->math = mathService;
+ pthread_rwlock_unlock(&consumer->rw_lock);
+ } else { //no locking
+ consumer->math = mathService;
+ }
+
+ //always update for reference counter
+// service_counter_t *new = malloc(sizeof(service_counter_t));
+// new->info.position = 0;
+// new->info.counter = 0;
+// new->info.math = mathService;
+// int found = false;
+// int pos;
+// for (pos = 0; !found && pos < FREELIST_LENGTH; pos += 1) {
+// found = __sync_bool_compare_and_swap(&(consumer->counters[pos]), NULL, new);
+// if (found) {
+// new->info.position = pos;
+// break;
+// }
+// }
+//
+// if (!found) {
+// printf("Cannot find free spot!!!!, will use 0\n");
+// consumer->counters[0] = new;
+// }
+//
+// int changed = false;
+// service_counter_t *old;
+// while (!changed) {
+// old = consumer->current;
+// changed = __sync_bool_compare_and_swap(&consumer->current, old, new);
+// }
+//
+// while (old->info.counter != 0) {usleep(10);}
+// consumer->counters[old->info.position] = NULL;
+// free(old);
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t consumer_removeMathService(consumer_pt consumer, math_service_pt mathService) {
+ if (consumer->currentLockingType == LOCKING_TYPE_NO_LOCKING) {
+ __sync_val_compare_and_swap(&consumer->math, mathService, NULL);
+ } else if (consumer->currentLockingType == LOCKING_TYPE_MUTEX) {
+ pthread_mutex_lock(&consumer->mutex);
+ if (consumer->math == mathService) {
+ consumer->math = NULL;
+ }
+ pthread_mutex_unlock(&consumer->mutex);
+ } else if (consumer->currentLockingType == LOCKING_TYPE_RCU) {
+ uatomic_cmpxchg(&consumer->math, mathService, NULL);
+ } else if (consumer->currentLockingType == LOCKING_TYPE_REFERENCE_COUNTER) {
+ //TODO DONT KNOWN IGNORE FOR NOW
+ }
+ return CELIX_SUCCESS;
+}
+
+static void * consumer_reference_run(run_info_t *info) {
+ int i;
+
+ gettimeofday(&info->begin, NULL);
+ for (i = 0; i < info->nrOfsamples; i += 1) {
+ info->result = consumer_reference_calc(info->result, i);
+ }
+ gettimeofday(&info->end, NULL);
+ return NULL;
+}
+
+static void * consumer_no_locking_run(run_info_t *info) {
+ int i;
+
+ gettimeofday(&info->begin, NULL);
+ for (i = 0; i < info->nrOfsamples; i += 1) {
+ if (info->consumer->math != NULL) {
+ info->result = info->consumer->math->calc(info->result, i);
+ } else {
+ info->skips +=1; //should not happen
+ }
+ }
+ gettimeofday(&info->end, NULL);
+ return NULL;
+}
+
+static void * consumer_mutex_run(run_info_t *info) {
+ int i;
+
+ gettimeofday(&info->begin, NULL);
+ for (i = 0; i < info->nrOfsamples; i += 1) {
+ pthread_mutex_lock(&info->consumer->mutex);
+ if (info->consumer->math != NULL) {
+ info->result = info->consumer->math->calc(info->result, i);
+ } else {
+ info->skips += 1; //should not happen
+ }
+ pthread_mutex_unlock(&info->consumer->mutex);
+ }
+ gettimeofday(&info->end, NULL);
+ return NULL;
+}
+
+static void * consumer_rw_lock_run(run_info_t *info) {
+ int i;
+ consumer_pt cons = info->consumer;
+ int result = info->result;
+ pthread_rwlock_t *lock = &cons->rw_lock;
+ int nrOfsamples = info->nrOfsamples;
+
+ gettimeofday(&info->begin, NULL);
+ for (i = 0; i < nrOfsamples; i += 1) {
+ pthread_rwlock_rdlock(lock);
+ if (cons->math != NULL) {
+ result = cons->math->calc(result, i);
+ } else {
+ info->skips += 1; //should not happen
+ }
+ pthread_rwlock_unlock(lock);
+ }
+ gettimeofday(&info->end, NULL);
+ info->result = result;
+ return NULL;
+}
+
+static void * consumer_rcu_run(run_info_t *info) {
+ rcu_register_thread();
+ int i;
+ math_service_pt service;
+
+ gettimeofday(&info->begin, NULL);
+ for (i = 0; i < info->nrOfsamples; i += 1) {
+ rcu_read_lock();
+ if (info->consumer->math != NULL) {
+ info->result = info->consumer->math->calc(info->result, i);
+ } else {
+ info->skips +=1; //should not happen
+ }
+ rcu_read_unlock();
+ }
+ gettimeofday(&info->end, NULL);
+ rcu_unregister_thread();
+ return NULL;
+}
+
+static void * consumer_reference_counting_run(run_info_t *info) {
+ int i;
+ service_counter_t posAndCount;
+
+ gettimeofday(&info->begin, NULL);
+ for (i = 0; i < info->nrOfsamples; i += 1) {
+ posAndCount.data = __sync_add_and_fetch((u_int64_t *)&info->consumer->current->data, 1);
+ volatile service_counter_t *serv = (volatile void *)info->consumer->counters[posAndCount.info.position];
+ if (serv->info.math != NULL) {
+ info->result = serv->info.math->calc(info->result, i);
+ } else {
+ info->skips += 1;
+ }
+ __sync_sub_and_fetch((u_int64_t *)&serv->data, -1);
+
+ //not service_counter will not be deleted...but can we still find it??? is info->consumer->serviceCounter still te same?
+ //change write to swap compare and then only changing the pointer is the counter is null?? not possible.. can compare counter , but not change pointer
+
+ //IDEA create a list with service_counter based on a id (number) this number is 32bit long and put a counter + id in a 64bit value.
+ //use this value to atomic increment and return value and use the id to retrieve the actual pointer. the value can be stored in the heap.
+ //A list with id is used to retrieve a pointer to the service. If the value is null the slot is available this can be check with
+ //compare_and_swap while looping through the list. The list can be extended when the end is reached and then a next list pointer can
+ //be used. This can also be a linked list and the limitation is the max 32bit uint value (of 16bits for 32bit platforms).
+ }
+
+ gettimeofday(&info->end, NULL);
+ return NULL;
+}
+
+//NOTE: copy implementation of the math_service->calc function, for reference.
+static int consumer_reference_calc(int arg1, int arg2) {
+ return arg1 * arg2 + arg2;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/math_provider/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/locking/math_provider/CMakeLists.txt b/examples/locking/math_provider/CMakeLists.txt
new file mode 100644
index 0000000..288d6ba
--- /dev/null
+++ b/examples/locking/math_provider/CMakeLists.txt
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+SET(BUNDLE_SYMBOLICNAME math_provider)
+SET(BUNDLE_VERSION 0.0.0)
+
+bundle(math_provider SOURCES
+ private/src/provider_activator
+ private/src/math_component
+)
+
+include_directories(public/include)
+include_directories(../benchmark/public/include)
+include_directories("${PROJECT_SOURCE_DIR}/framework/public/include")
+include_directories("${PROJECT_SOURCE_DIR}/utils/public/include")
+include_directories("${PROJECT_SOURCE_DIR}/shell/public/include")
+include_directories(private/include)
+target_link_libraries(math_provider celix_framework)
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/math_provider/private/include/math_component.h
----------------------------------------------------------------------
diff --git a/examples/locking/math_provider/private/include/math_component.h b/examples/locking/math_provider/private/include/math_component.h
new file mode 100644
index 0000000..0b55d10
--- /dev/null
+++ b/examples/locking/math_provider/private/include/math_component.h
@@ -0,0 +1,14 @@
+#ifndef MATH_COMPONENT_H_
+#define MATH_COMPONENT_H_
+
+#include "celix_errno.h"
+
+typedef struct math_component *math_component_pt;
+
+celix_status_t mathComponent_create(math_component_pt *math);
+celix_status_t mathComponent_destroy(math_component_pt math);
+
+int mathComponent_calc(math_component_pt math, int arg1, int arg2);
+
+
+#endif /* MATH_COMPONENT_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/math_provider/private/src/math_component.c
----------------------------------------------------------------------
diff --git a/examples/locking/math_provider/private/src/math_component.c b/examples/locking/math_provider/private/src/math_component.c
new file mode 100644
index 0000000..2937fee
--- /dev/null
+++ b/examples/locking/math_provider/private/src/math_component.c
@@ -0,0 +1,28 @@
+/*
+ * math.c
+ *
+ * Created on: Oct 8, 2014
+ * Author: dl436
+ */
+
+#include "math_component.h"
+
+struct math_component {
+ //emtpy
+};
+
+celix_status_t mathComponent_create(math_component_pt *math) {
+ (*math) = malloc(sizeof(struct math_component));
+ return CELIX_SUCCESS;
+}
+
+celix_status_t mathComponent_destroy(math_component_pt math) {
+ free(math);
+ return CELIX_SUCCESS;
+}
+
+int mathComponent_calc(math_component_pt math, int arg1, int arg2) {
+ return arg1 * arg2 + arg2;
+}
+
+
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/math_provider/private/src/provider_activator.c
----------------------------------------------------------------------
diff --git a/examples/locking/math_provider/private/src/provider_activator.c b/examples/locking/math_provider/private/src/provider_activator.c
new file mode 100644
index 0000000..319980f
--- /dev/null
+++ b/examples/locking/math_provider/private/src/provider_activator.c
@@ -0,0 +1,219 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements. See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership. The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+/*
+ * echo_server_activator.c
+ *
+ * \date Sep 21, 2010
+ * \author <a href="mailto:celix-dev@incubator.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <sys/time.h>
+
+#include "bundle_activator.h"
+#include "bundle_context.h"
+#include "service_registration.h"
+
+#include "math_service.h"
+#include "frequency_service.h"
+#include "math_component.h"
+
+typedef struct activator {
+ bundle_context_pt context;
+
+ frequency_service_pt freqService;
+ service_registration_pt freqRegistration;
+
+ math_component_pt math;
+ math_service_pt mathService;
+ char *benchmarkName;
+ service_registration_pt registration;
+
+ uint updateFrequency;
+ uint nrOfThreads;
+ pthread_t *threads;
+
+
+ volatile uint counter;
+ struct timeval beginMeasurement;
+ struct timeval endMeasurement;
+} activator_t;
+
+static int calc(int arg1, int arg2);
+static void run(activator_t *activator);
+static void setFrequency(activator_t *activator, uint freq);
+static void setNrOfThreads(activator_t *activator, uint nrOfThreads);
+static void resetCounter(activator_t *activator);
+static void stopThreads(activator_t *activator);
+static void startThreads(activator_t *activator, uint nrOfThreads);
+static uint getCounter(activator_t *activator);
+static void setBenchmarkName(activator_t *activator, char *benchmark);
+static math_service_pt registerMath(activator_t *activator, service_registration_pt *reg);
+
+celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
+ activator_t * activator = malloc(sizeof(*activator));
+ activator->context = context;
+ activator->benchmarkName = NULL;
+ activator->freqService = NULL;
+ activator->freqRegistration = NULL;
+ activator->updateFrequency = 0;
+ activator->nrOfThreads = 0;
+ activator->math = NULL;
+
+ mathComponent_create(&activator->math);
+
+ *userData = activator;
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
+ celix_status_t status = CELIX_SUCCESS;
+ struct activator * activator = userData;
+
+ activator->mathService = malloc(sizeof(*activator->mathService));
+ activator->mathService->handle = activator->math;
+ activator->mathService->calc = (void *)mathComponent_calc;
+ bundleContext_registerService(activator->context, MATH_SERVICE_NAME, activator->mathService, NULL, &activator->registration);
+
+ activator->freqService = malloc(sizeof(*activator->freqService));
+ activator->freqService->handle = (void *)activator;
+ activator->freqService->setFrequency = (void *)setFrequency;
+ activator->freqService->resetCounter = (void *)resetCounter;
+ activator->freqService->getCounter = (void *)getCounter;
+ activator->freqService->setBenchmarkName = (void *)setBenchmarkName;
+ activator->freqService->setNrOfThreads = (void *)setNrOfThreads;
+ bundleContext_registerService(activator->context, FREQUENCY_SERVICE_NAME, activator->freqService, NULL, &activator->freqRegistration);
+
+ startThreads(activator, activator->nrOfThreads);
+
+ return status;
+}
+
+celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
+ struct activator * activator = userData;
+
+ printf("Stopping service registration thread\n");
+ stopThreads(activator);
+
+ //TODO deregister service & freqService
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
+ struct echoActivator * activator = userData;
+
+ //TODO free service & freqService struct
+
+ free(activator);
+
+ return CELIX_SUCCESS;
+}
+
+static int calc(int arg1, int arg2) {
+ return arg1 * arg2 + arg2;
+}
+
+static void stopThreads(activator_t *activator) {
+ //cancel and join threads
+ if (activator->threads != NULL) {
+ for (int i = 0 ; i < activator->nrOfThreads ; i += 1) {
+ pthread_cancel(activator->threads[i]);
+ pthread_join(activator->threads[i], NULL);
+ }
+ }
+}
+
+static void startThreads(activator_t *activator, uint nrOfThreads) {
+ activator->threads = malloc(sizeof(pthread_t) * nrOfThreads);
+ for (int i = 0 ; i < nrOfThreads ; i += 1) {
+ pthread_create(&activator->threads[i], NULL, (void *)run, activator);
+ }
+ activator->nrOfThreads = nrOfThreads;
+}
+
+static void run(activator_t *activator) {
+ service_registration_pt currentReg = NULL;
+ service_registration_pt prevReg = NULL;
+ math_service_pt current = NULL;
+ math_service_pt prev = NULL;
+ while (1) {
+ pthread_testcancel(); //NOTE no clean exit still need to clear a register service
+ uint delayInMicroseconds = activator->updateFrequency == 0 ? 0 : (1000 * 1000) / activator->updateFrequency;
+ if (delayInMicroseconds > 0) {
+ prevReg = currentReg;
+ prev = current;
+
+ currentReg = NULL;
+ current = registerMath(activator, ¤tReg);
+
+ if (prevReg != NULL) {
+ serviceRegistration_unregister(prevReg);
+ free(prev);
+ }
+ }
+ usleep(delayInMicroseconds > 0 ? delayInMicroseconds : 1000000);
+ }
+}
+
+static math_service_pt registerMath(activator_t *activator, service_registration_pt *reg) {
+ math_service_pt serv = NULL;
+ serv = malloc(sizeof(*activator->mathService));
+ serv->handle = activator->math;
+ serv->calc = (void *)mathComponent_calc;
+ properties_pt props = properties_create();
+ if (activator->benchmarkName != NULL) { //TODO FIXME race condition
+ properties_set(props, "benchmark", activator->benchmarkName);
+ }
+ bundleContext_registerService(activator->context, MATH_SERVICE_NAME,
+ serv, props, reg);
+ activator->counter += 1;
+ return serv;
+}
+
+static void setBenchmarkName(activator_t *activator, char *benchmark) {
+ char *old = activator->benchmarkName;
+ activator->benchmarkName = strdup(benchmark);
+ free(old);
+ if (activator->updateFrequency == 0) {
+ service_registration_pt reg = NULL;
+ registerMath(activator, ®); //TODO service will not be cleaned up !
+ }
+}
+
+static void setFrequency(activator_t *activator, uint freq) {
+ printf("Setting frequency to %i\n", freq);
+ activator->updateFrequency = freq;
+}
+
+static void setNrOfThreads(activator_t *activator, uint nrOfThreads) {
+ stopThreads(activator);
+ startThreads(activator, nrOfThreads);
+}
+
+static void resetCounter(activator_t *activator) {
+ activator->counter = 0;
+}
+
+static uint getCounter(activator_t *activator) {
+ return activator->counter;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/modified_bool_benchmark/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/locking/modified_bool_benchmark/CMakeLists.txt b/examples/locking/modified_bool_benchmark/CMakeLists.txt
new file mode 100644
index 0000000..46ceb7a
--- /dev/null
+++ b/examples/locking/modified_bool_benchmark/CMakeLists.txt
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+SET(BUNDLE_SYMBOLICNAME bool_benchmark)
+SET(BUNDLE_VERSION 0.0.0)
+
+bundle(modified_bool_benchmark SOURCES
+ ../benchmark/public/src/benchmark_activator
+ private/src/modified_bool_benchmark
+)
+
+include_directories(public/include)
+include_directories(../benchmark/public/include)
+include_directories("${PROJECT_SOURCE_DIR}/framework/public/include")
+include_directories("${PROJECT_SOURCE_DIR}/utils/public/include")
+include_directories("${PROJECT_SOURCE_DIR}/shell/public/include")
+target_link_libraries(modified_bool_benchmark celix_framework)
+
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/modified_bool_benchmark/private/src/modified_bool_benchmark.c
----------------------------------------------------------------------
diff --git a/examples/locking/modified_bool_benchmark/private/src/modified_bool_benchmark.c b/examples/locking/modified_bool_benchmark/private/src/modified_bool_benchmark.c
new file mode 100644
index 0000000..b482b2c
--- /dev/null
+++ b/examples/locking/modified_bool_benchmark/private/src/modified_bool_benchmark.c
@@ -0,0 +1,162 @@
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+#include "array_list.h"
+
+#include "benchmark.h"
+#include "math_service.h"
+
+static const char * const BENCHMARK_NAME = "MODIFIED_BIT";
+static const double SAMPLE_FACTOR = 1;
+static const useconds_t SLEEP_TIME = 10;
+
+typedef struct thread_info {
+ benchmark_pt benchmark;
+ unsigned int result;
+ struct timeval begin;
+ struct timeval end;
+ int skips;
+ bool isModified;
+ bool isUpdated;
+} thread_info_t;
+
+struct benchmark {
+ pthread_mutex_t mutex;
+ math_service_pt math;
+ int nrOfSamples;
+ int nrOfThreads;
+ thread_info_t *threads;
+};
+
+static void benchmark_thread(thread_info_t *info);
+
+celix_status_t benchmark_create(benchmark_pt *benchmark) {
+ (*benchmark) = malloc(sizeof(struct benchmark));
+ (*benchmark)->math = NULL;
+ pthread_mutex_init(&(*benchmark)->mutex, NULL);
+ return CELIX_SUCCESS;
+}
+
+celix_status_t benchmark_destroy(benchmark_pt benchmark) {
+ //free threads array
+ free(benchmark);
+ return CELIX_SUCCESS;
+}
+
+benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples) {
+ int i;
+ pthread_t threads[nrOfThreads];
+ thread_info_t infos[nrOfThreads];
+ benchmark_result_t result;
+ unsigned long elapsedTime = 0;
+
+ benchmark->threads = infos;
+ benchmark->nrOfSamples = nrOfSamples;
+ benchmark->nrOfThreads = nrOfThreads;
+
+ result.skips =0;
+ pthread_mutex_lock(&benchmark->mutex);
+ for (i = 0 ; i < nrOfThreads ; i += 1) {
+ infos[i].benchmark = benchmark;
+ infos[i].skips = 0;
+ infos[i].result = rand();
+ infos[i].isUpdated = false;
+ infos[i].isModified = false;
+ pthread_create(&threads[i], NULL, (void *)benchmark_thread, &infos[i]);
+ }
+ pthread_mutex_unlock(&benchmark->mutex);
+
+ for (i = 0; i < nrOfThreads ; i += 1) {
+ pthread_join(threads[i], NULL);
+ elapsedTime += ((infos[i].end.tv_sec - infos[i].begin.tv_sec) * 1000000) + (infos[i].end.tv_usec - infos[i].begin.tv_usec);
+ result.skips += infos[i].skips;
+ }
+
+ result.averageCallTimeInNanoseconds = ((double)elapsedTime * 1000) / (nrOfSamples * nrOfThreads);
+ result.callFrequencyInMhz = ((double)(nrOfSamples * nrOfThreads) / elapsedTime);
+ result.nrOfThreads = nrOfThreads;
+ result.nrOfsamples = nrOfSamples;
+
+ return result;
+}
+
+static void benchmark_thread(thread_info_t *info) {
+ int i = 0;
+
+ math_service_pt local = info->benchmark->math;
+ int nrOfSamples = info->benchmark->nrOfSamples;
+
+ gettimeofday(&info->begin, NULL);
+ while (i < nrOfSamples) {
+ if (!info->isModified) {
+ if (local != NULL) {
+ info->result = local->calc(local->handle, info->result, i);
+ } else {
+ info->skips += 1; //should not happen
+ }
+ i += 1;
+ } else {
+ local = info->benchmark->math;
+ info->isModified = false;
+ }
+ }
+ gettimeofday(&info->end, NULL);
+
+}
+
+char * benchmark_getName(benchmark_pt benchmark) {
+ return (char *)BENCHMARK_NAME;
+}
+
+celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService) {
+ int i;
+
+ pthread_mutex_lock(&benchmark->mutex);
+ benchmark->math = mathService;
+ pthread_mutex_unlock(&benchmark->mutex);
+
+ //inform threads to update servicd
+ for (i = 0 ; i < benchmark->nrOfSamples ; i += 1) {
+ benchmark->threads[i].isModified = true;
+ }
+
+ //Wait till al thread are not in a modified state, e.g. update to date mathService and not using the old service
+ for (i = 0; i < benchmark->nrOfThreads ; i += 1) {
+ if (benchmark->threads[i].isModified) {
+ usleep(SLEEP_TIME);
+ }
+ }
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService) {
+ pthread_mutex_lock(&benchmark->mutex);
+ if (benchmark->math == mathService) {
+ benchmark->math = NULL;
+ }
+ pthread_mutex_unlock(&benchmark->mutex);
+
+ //inform threads to update servicd
+ int i;
+ for (i = 0 ; i < benchmark->nrOfThreads ; i += 1) {
+ benchmark->threads[i].isModified = true;
+ }
+
+ //Wait till al thread are not in a modified state, e.g. update to date mathService and not using the old service
+ for (i = 0; i < benchmark->nrOfThreads ; i += 1) {
+ if (benchmark->threads[i].isModified) {
+ usleep(SLEEP_TIME);
+ }
+ }
+
+
+ return CELIX_SUCCESS;
+}
+
+double benchmark_getSampleFactor(benchmark_pt benchmark) {
+ return SAMPLE_FACTOR;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/mutex_benchmark/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/locking/mutex_benchmark/CMakeLists.txt b/examples/locking/mutex_benchmark/CMakeLists.txt
new file mode 100644
index 0000000..b822ffa
--- /dev/null
+++ b/examples/locking/mutex_benchmark/CMakeLists.txt
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+SET(BUNDLE_SYMBOLICNAME mutex_benchmark)
+SET(BUNDLE_VERSION 0.0.0)
+
+bundle(mutex_benchmark SOURCES
+ ../benchmark/public/src/benchmark_activator
+ private/src/mutex_benchmark
+)
+
+include_directories(public/include)
+include_directories(../benchmark/public/include)
+include_directories("${PROJECT_SOURCE_DIR}/framework/public/include")
+include_directories("${PROJECT_SOURCE_DIR}/utils/public/include")
+include_directories("${PROJECT_SOURCE_DIR}/shell/public/include")
+target_link_libraries(mutex_benchmark celix_framework)
+
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/mutex_benchmark/private/src/mutex_benchmark.c
----------------------------------------------------------------------
diff --git a/examples/locking/mutex_benchmark/private/src/mutex_benchmark.c b/examples/locking/mutex_benchmark/private/src/mutex_benchmark.c
new file mode 100644
index 0000000..3cacfb8
--- /dev/null
+++ b/examples/locking/mutex_benchmark/private/src/mutex_benchmark.c
@@ -0,0 +1,117 @@
+/*
+ * mutex_benchmark.c
+ *
+ * Created on: Feb 13, 2014
+ * Author: dl436
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "benchmark.h"
+
+static const char * const BENCHMARK_NAME = "MUTEX";
+static const double SAMPLE_FACTOR = 1;
+
+struct benchmark {
+ pthread_mutex_t mutex;
+ math_service_pt math;
+};
+
+typedef struct thread_info {
+ benchmark_pt benchmark;
+ int nrOfSamples;
+ unsigned int result;
+ struct timeval begin;
+ struct timeval end;
+ int skips;
+} thread_info_t;
+
+static void benchmark_thread(thread_info_t *info);
+
+celix_status_t benchmark_create(benchmark_pt *benchmark) {
+ (*benchmark) = malloc(sizeof(struct benchmark));
+ (*benchmark)->math = NULL;
+ pthread_mutex_init(&(*benchmark)->mutex, NULL);
+ return CELIX_SUCCESS;
+}
+
+celix_status_t benchmark_destroy(benchmark_pt benchmark) {
+ free(benchmark);
+ return CELIX_SUCCESS;
+}
+
+benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples) {
+ int i;
+ pthread_t threads[nrOfThreads];
+ thread_info_t infos[nrOfThreads];
+ benchmark_result_t result;
+ unsigned long elapsedTime = 0;
+
+ result.skips =0;
+
+ for (i = 0 ; i < nrOfThreads ; i += 1) {
+ infos[i].benchmark = benchmark;
+ infos[i].nrOfSamples = nrOfSamples;
+ infos[i].skips = 0;
+ infos[i].result = rand();
+ pthread_create(&threads[i], NULL, (void *)benchmark_thread, &infos[i]);
+ }
+
+ for (i = 0; i < nrOfThreads ; i += 1) {
+ pthread_join(threads[i], NULL);
+ elapsedTime += ((infos[i].end.tv_sec - infos[i].begin.tv_sec) * 1000000) + (infos[i].end.tv_usec - infos[i].begin.tv_usec);
+ result.skips += infos[i].skips;
+ }
+
+ result.averageCallTimeInNanoseconds = ((double)elapsedTime * 1000) / (nrOfSamples * nrOfThreads);
+ result.callFrequencyInMhz = ((double)(nrOfSamples * nrOfThreads) / elapsedTime);
+ result.nrOfThreads = nrOfThreads;
+ result.nrOfsamples = nrOfSamples;
+
+ return result;
+}
+
+static void benchmark_thread(thread_info_t *info) {
+ int i;
+
+ gettimeofday(&info->begin, NULL);
+ for (i = 0; i < info->nrOfSamples; i += 1) {
+ pthread_mutex_lock(&info->benchmark->mutex);
+ if (info->benchmark->math != NULL) {
+ info->result = info->benchmark->math->calc(info->benchmark->math->handle, info->result, i);
+ } else {
+ info->skips += 1; //should not happen
+ }
+ pthread_mutex_unlock(&info->benchmark->mutex);
+ }
+ gettimeofday(&info->end, NULL);
+
+}
+
+char * benchmark_getName(benchmark_pt benchmark) {
+ return (char *)BENCHMARK_NAME;
+}
+
+celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService) {
+ pthread_mutex_lock(&benchmark->mutex);
+ benchmark->math = mathService;
+ pthread_mutex_unlock(&benchmark->mutex);
+ return CELIX_SUCCESS;
+}
+
+celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService) {
+ pthread_mutex_lock(&benchmark->mutex);
+ if (benchmark->math == mathService) {
+ benchmark->math = NULL;
+ }
+ pthread_mutex_unlock(&benchmark->mutex);
+ return CELIX_SUCCESS;
+
+}
+
+double benchmark_getSampleFactor(benchmark_pt benchmark) {
+ return SAMPLE_FACTOR;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/reference_benchmark/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/locking/reference_benchmark/CMakeLists.txt b/examples/locking/reference_benchmark/CMakeLists.txt
new file mode 100644
index 0000000..592bb9c
--- /dev/null
+++ b/examples/locking/reference_benchmark/CMakeLists.txt
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+SET(BUNDLE_SYMBOLICNAME reference_benchmark)
+SET(BUNDLE_VERSION 0.0.0)
+
+bundle(reference_benchmark SOURCES
+ ../benchmark/public/src/benchmark_activator
+ private/src/reference_benchmark
+)
+
+include_directories(public/include)
+include_directories(../benchmark/public/include)
+include_directories("${PROJECT_SOURCE_DIR}/framework/public/include")
+include_directories("${PROJECT_SOURCE_DIR}/utils/public/include")
+include_directories("${PROJECT_SOURCE_DIR}/shell/public/include")
+target_link_libraries(reference_benchmark celix_framework)
+
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/reference_benchmark/private/src/reference_benchmark.c
----------------------------------------------------------------------
diff --git a/examples/locking/reference_benchmark/private/src/reference_benchmark.c b/examples/locking/reference_benchmark/private/src/reference_benchmark.c
new file mode 100644
index 0000000..f4bb93f
--- /dev/null
+++ b/examples/locking/reference_benchmark/private/src/reference_benchmark.c
@@ -0,0 +1,116 @@
+/*
+ * mutex_benchmark.c
+ *
+ * Created on: Feb 13, 2014
+ * Author: dl436
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+#include "benchmark.h"
+
+static const char * const BENCHMARK_NAME = "REFERENCE";
+static const double SAMPLE_FACTOR = 100;
+
+typedef struct thread_info {
+ benchmark_pt benchmark;
+ int nrOfSamples;
+ unsigned int result;
+ struct timeval begin;
+ struct timeval end;
+ int skips;
+} thread_info_t;
+
+static void benchmark_thread(thread_info_t *info);
+static int benchmark_calc(int arg1, int arg2);
+
+celix_status_t benchmark_create(benchmark_pt *benchmark) {
+ //do nothing
+ return CELIX_SUCCESS;
+}
+
+celix_status_t benchmark_destroy(benchmark_pt benchmark) {
+ //do nothing
+ return CELIX_SUCCESS;
+}
+
+benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples) {
+ int i;
+ pthread_t threads[nrOfThreads];
+ thread_info_t infos[nrOfThreads];
+ benchmark_result_t result;
+ unsigned long elapsedTime = 0;
+
+ result.skips =0;
+
+ for (i = 0 ; i < nrOfThreads ; i += 1) {
+ infos[i].benchmark = benchmark;
+ infos[i].nrOfSamples = nrOfSamples;
+ infos[i].skips = 0;
+ infos[i].result = rand();
+ pthread_create(&threads[i], NULL, (void *)benchmark_thread, &infos[i]);
+ }
+
+ for (i = 0; i < nrOfThreads ; i += 1) {
+ pthread_join(threads[i], NULL);
+ elapsedTime += ((infos[i].end.tv_sec - infos[i].begin.tv_sec) * 1000000) + (infos[i].end.tv_usec - infos[i].begin.tv_usec);
+ result.skips += infos[i].skips;
+ }
+
+ result.averageCallTimeInNanoseconds = elapsedTime;
+ result.averageCallTimeInNanoseconds *= 1000;
+ result.averageCallTimeInNanoseconds /= nrOfSamples;
+ result.averageCallTimeInNanoseconds /= nrOfThreads;
+ result.callFrequencyInMhz = ((double)(nrOfSamples * nrOfThreads) / elapsedTime);
+ result.nrOfThreads = nrOfThreads;
+ result.nrOfsamples = nrOfSamples;
+
+ return result;
+}
+
+static void benchmark_thread(thread_info_t *info) {
+ int i;
+
+ int result = info->result;
+ struct timeval *begin = &info->begin;
+ struct timeval *end = &info->end;
+ int nrOFSamples = info->nrOfSamples;
+
+
+ gettimeofday(begin, NULL);
+ for (i = 0; i < nrOFSamples; i += 1) {
+ result = benchmark_calc(result, i);
+ }
+ gettimeofday(end, NULL);
+
+ info->result = result;
+}
+
+char * benchmark_getName(benchmark_pt benchmark) {
+ return (char *)BENCHMARK_NAME;
+}
+
+celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService) {
+ //ignore service is not used
+ return CELIX_SUCCESS;
+}
+
+celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService) {
+ //ignore service is not used
+ return CELIX_SUCCESS;
+
+}
+
+/*
+ * Same implementation as the math_service. This function is used a reference.
+ */
+static int benchmark_calc(int arg1, int arg2) {
+ return arg1 * arg2 + arg2;
+}
+
+double benchmark_getSampleFactor(benchmark_pt benchmark) {
+ return SAMPLE_FACTOR;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/start_stop_benchmark/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/locking/start_stop_benchmark/CMakeLists.txt b/examples/locking/start_stop_benchmark/CMakeLists.txt
new file mode 100644
index 0000000..bca651e
--- /dev/null
+++ b/examples/locking/start_stop_benchmark/CMakeLists.txt
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+SET(BUNDLE_SYMBOLICNAME stop_benchmark)
+SET(BUNDLE_VERSION 0.0.0)
+
+bundle(start_stop_benchmark SOURCES
+ ../benchmark/public/src/benchmark_activator
+ private/src/start_stop_benchmark
+)
+
+include_directories(public/include)
+include_directories(../benchmark/public/include)
+include_directories("${PROJECT_SOURCE_DIR}/framework/public/include")
+include_directories("${PROJECT_SOURCE_DIR}/utils/public/include")
+include_directories("${PROJECT_SOURCE_DIR}/shell/public/include")
+target_link_libraries(start_stop_benchmark celix_framework)
+
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/examples/locking/start_stop_benchmark/private/src/start_stop_benchmark.c
----------------------------------------------------------------------
diff --git a/examples/locking/start_stop_benchmark/private/src/start_stop_benchmark.c b/examples/locking/start_stop_benchmark/private/src/start_stop_benchmark.c
new file mode 100644
index 0000000..1d445c5
--- /dev/null
+++ b/examples/locking/start_stop_benchmark/private/src/start_stop_benchmark.c
@@ -0,0 +1,189 @@
+/*
+ * mutex_benchmark.c
+ *
+ * Created on: Feb 13, 2014
+ * Author: dl436
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <stdio.h>
+
+#include "benchmark.h"
+
+static const char * const BENCHMARK_NAME = "INTR_CONT";
+static const double SAMPLE_FACTOR = 100;
+static const __useconds_t WAIT_TIME = 1; //100 * 1000;
+
+typedef enum benchmark_state {
+ BENCHMARK_STATE_INTERRUPTED,
+ BENCHMARK_STATE_RUNNING
+} benchmark_state_t;
+
+struct benchmark {
+ int nrOfThreads;
+ pthread_mutex_t mutex; //write protect for state
+ math_service_pt math;
+ benchmark_state_t state;
+ int threadsRunning;
+};
+
+typedef struct thread_info {
+ benchmark_pt benchmark;
+ int nrOfSamples;
+ unsigned int result;
+ struct timeval begin;
+ struct timeval end;
+ int skips;
+} thread_info_t;
+
+static void benchmark_thread(thread_info_t *info);
+static void benchmark_runSamples(thread_info_t *info, int *i, volatile benchmark_state_t *state);
+static void benchmark_interrupt(benchmark_pt benchmark);
+static void benchmark_continue(benchmark_pt benchmark);
+
+celix_status_t benchmark_create(benchmark_pt *benchmark) {
+ (*benchmark) = malloc(sizeof(struct benchmark));
+ (*benchmark)->math = NULL;
+ (*benchmark)->state = BENCHMARK_STATE_INTERRUPTED;
+ (*benchmark)->nrOfThreads = 0;
+ (*benchmark)->threadsRunning = 0;
+
+ pthread_mutex_init(&(*benchmark)->mutex, NULL);
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t benchmark_destroy(benchmark_pt benchmark) {
+ free(benchmark);
+
+ return CELIX_SUCCESS;
+}
+
+benchmark_result_t benchmark_run(benchmark_pt benchmark, int nrOfThreads, int nrOfSamples) {
+ int i;
+ pthread_t threads[nrOfThreads];
+ thread_info_t infos[nrOfThreads];
+ int isThreadRunning[nrOfThreads];
+ benchmark_result_t result;
+ unsigned long elapsedTime = 0;
+ result.skips =0;
+
+ for (i = 0 ; i < nrOfThreads ; i += 1) {
+ infos[i].benchmark = benchmark;
+ infos[i].nrOfSamples = nrOfSamples;
+ infos[i].skips = 0;
+ infos[i].result = rand();
+ pthread_create(&threads[i], NULL, (void *)benchmark_thread, &infos[i]);
+ }
+
+ benchmark->nrOfThreads = nrOfThreads;
+
+ for (i = 0; i < nrOfThreads ; i += 1) {
+ pthread_join(threads[i], NULL);
+ elapsedTime += ((infos[i].end.tv_sec - infos[i].begin.tv_sec) * 1000000) + (infos[i].end.tv_usec - infos[i].begin.tv_usec);
+ result.skips += infos[i].skips;
+ }
+
+ benchmark->nrOfThreads = 0;
+
+ result.averageCallTimeInNanoseconds = elapsedTime;
+ result.averageCallTimeInNanoseconds *= 1000;
+ result.averageCallTimeInNanoseconds /= nrOfSamples;
+ result.averageCallTimeInNanoseconds /= nrOfThreads;
+ result.callFrequencyInMhz = ((double)(nrOfSamples * nrOfThreads) / elapsedTime);
+ result.nrOfThreads = nrOfThreads;
+ result.nrOfsamples = nrOfSamples;
+
+ return result;
+}
+
+static void benchmark_thread(thread_info_t *info) {
+ int i = 0;
+
+ gettimeofday(&info->begin, NULL);
+ while (i < info->nrOfSamples) {
+ if (info->benchmark->state == BENCHMARK_STATE_RUNNING ) {
+ //TODO race condition?? or not because of the mutex on changing the state
+ __sync_add_and_fetch(&info->benchmark->threadsRunning, 1);
+ benchmark_runSamples(info, &i, &info->benchmark->state);
+ __sync_sub_and_fetch(&info->benchmark->threadsRunning, 1);
+ } else {
+ usleep(WAIT_TIME);
+ }
+ }
+ gettimeofday(&info->end, NULL);
+
+}
+
+static void benchmark_runSamples(thread_info_t *info, int *i, volatile benchmark_state_t *state) {
+ int nrOfSamples = info->nrOfSamples;
+ unsigned int result = info->result;
+ math_service_pt math = info->benchmark->math;
+
+ for (; *i < nrOfSamples && *state == BENCHMARK_STATE_RUNNING; *i += 1) {
+ result = math->calc(math->handle, result, *i);
+ }
+
+ info->result = result;
+}
+
+char * benchmark_getName(benchmark_pt benchmark) {
+ return (char *)BENCHMARK_NAME;
+}
+
+static void benchmark_continue(benchmark_pt benchmark) {
+ benchmark->state = BENCHMARK_STATE_RUNNING;
+ unsigned long waitTime = 0;
+ while (benchmark->threadsRunning < benchmark->nrOfThreads) {
+ usleep(WAIT_TIME);
+ waitTime += WAIT_TIME;
+ if (waitTime > 1000 * 1000 * 2) {
+ printf("still waiting to stop, running threads are %i\n",
+ benchmark->threadsRunning);
+ }
+ }
+}
+
+static void benchmark_interrupt(benchmark_pt benchmark) {
+ int i = 0;
+ unsigned long waitTime = 0;
+ if (benchmark->state == BENCHMARK_STATE_RUNNING) {
+ benchmark->state = BENCHMARK_STATE_INTERRUPTED;
+ while (benchmark->threadsRunning > 0) {
+ usleep(WAIT_TIME);
+ waitTime += WAIT_TIME;
+ if (waitTime > 1000 * 1000 * 2) {
+ printf("still waiting to stop, running threads are %i\n",
+ benchmark->threadsRunning);
+ }
+ }
+ }
+}
+
+celix_status_t benchmark_addMathService(benchmark_pt benchmark, math_service_pt mathService) {
+ pthread_mutex_lock(&benchmark->mutex);
+ benchmark_interrupt(benchmark);
+ benchmark->math = mathService;
+ benchmark_continue(benchmark);
+ pthread_mutex_unlock(&benchmark->mutex);
+ return CELIX_SUCCESS;
+}
+
+celix_status_t benchmark_removeMathService(benchmark_pt benchmark, math_service_pt mathService) {
+ pthread_mutex_lock(&benchmark->mutex);
+ if (benchmark->math == mathService) {
+ benchmark_interrupt(benchmark);
+ benchmark->math = NULL;
+ benchmark_continue(benchmark);
+ }
+ pthread_mutex_unlock(&benchmark->mutex);
+ return CELIX_SUCCESS;
+
+}
+
+double benchmark_getSampleFactor(benchmark_pt benchmark) {
+ return SAMPLE_FACTOR;
+}
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/include/service_reference_private.h
----------------------------------------------------------------------
diff --git a/framework/private/include/service_reference_private.h b/framework/private/include/service_reference_private.h
index b297c14..114eae1 100644
--- a/framework/private/include/service_reference_private.h
+++ b/framework/private/include/service_reference_private.h
@@ -33,12 +33,17 @@
struct serviceReference {
bundle_pt bundle;
struct serviceRegistration * registration;
+
+ size_t refCount;
+ celix_thread_mutex_t mutex; //protects refCount
};
celix_status_t serviceReference_create(bundle_pt bundle, service_registration_pt registration, service_reference_pt *reference);
-celix_status_t serviceReference_destroy(service_reference_pt *reference);
+
+void serviceReference_retain(service_reference_pt ref);
+void serviceReference_release(service_reference_pt ref);
celix_status_t serviceReference_invalidate(service_reference_pt reference);
-celix_status_t serviceRefernce_isValid(service_reference_pt reference, bool *result);
+celix_status_t serviceReference_isValid(service_reference_pt reference, bool *result);
#endif /* SERVICE_REFERENCE_PRIVATE_H_ */
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/include/service_registration_private.h
----------------------------------------------------------------------
diff --git a/framework/private/include/service_registration_private.h b/framework/private/include/service_registration_private.h
index 8f31a14..081f996 100644
--- a/framework/private/include/service_registration_private.h
+++ b/framework/private/include/service_registration_private.h
@@ -51,11 +51,15 @@ struct serviceRegistration {
struct service *services;
int nrOfServices;
+
+ size_t refCount; //protected by mutex
};
service_registration_pt serviceRegistration_create(service_registry_pt registry, bundle_pt bundle, char * serviceName, long serviceId, void * serviceObject, properties_pt dictionary);
service_registration_pt serviceRegistration_createServiceFactory(service_registry_pt registry, bundle_pt bundle, char * serviceName, long serviceId, void * serviceObject, properties_pt dictionary);
-celix_status_t serviceRegistration_destroy(service_registration_pt registration);
+
+void serviceRegistration_retain(service_registration_pt registration);
+void serviceRegistration_release(service_registration_pt registration);
bool serviceRegistration_isValid(service_registration_pt registration);
void serviceRegistration_invalidate(service_registration_pt registration);
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/include/service_registry_private.h
----------------------------------------------------------------------
diff --git a/framework/private/include/service_registry_private.h b/framework/private/include/service_registry_private.h
index 7bda186..d89f28e 100644
--- a/framework/private/include/service_registry_private.h
+++ b/framework/private/include/service_registry_private.h
@@ -50,6 +50,7 @@ struct usageCount {
unsigned int count;
service_reference_pt reference;
void * service;
+ service_registration_pt registration;
};
typedef struct usageCount * usage_count_pt;
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/src/properties.c
----------------------------------------------------------------------
diff --git a/framework/private/src/properties.c b/framework/private/src/properties.c
index 14455c4..271eed1 100644
--- a/framework/private/src/properties.c
+++ b/framework/private/src/properties.c
@@ -180,6 +180,28 @@ void properties_store(properties_pt properties, char * filename, char * header)
}
}
+celix_status_t properties_copy(properties_pt properties, properties_pt *out) {
+ celix_status_t status = CELIX_SUCCESS;
+ properties_pt copy = properties_create();
+
+ if (copy != NULL) {
+ hash_map_iterator_pt iter = hashMapIterator_create(properties);
+ while (hashMapIterator_hasNext(iter)) {
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+ char *key = hashMapEntry_getKey(entry);
+ char *value = hashMapEntry_getValue(entry);
+ properties_set(copy, key, value);
+ }
+ hashMapIterator_destroy(iter);
+ } else {
+ status = CELIX_ENOMEM;
+ }
+
+ if (status == CELIX_SUCCESS) {
+ *out = copy;
+ }
+}
+
char * properties_get(properties_pt properties, char * key) {
return hashMap_get(properties, key);
}
http://git-wip-us.apache.org/repos/asf/celix/blob/e0231e51/framework/private/src/service_reference.c
----------------------------------------------------------------------
diff --git a/framework/private/src/service_reference.c b/framework/private/src/service_reference.c
index 528b4be..24fdc99 100644
--- a/framework/private/src/service_reference.c
+++ b/framework/private/src/service_reference.c
@@ -28,6 +28,7 @@
#include <constants.h>
#include <stdint.h>
#include <utils.h>
+#include <assert.h>
#include "service_reference.h"
@@ -39,29 +40,53 @@
#include "bundle.h"
#include "celix_log.h"
-celix_status_t serviceReference_create(bundle_pt bundle, service_registration_pt registration, service_reference_pt *reference) {
+static void serviceReference_destroy(service_reference_pt);
+
+celix_status_t serviceReference_create(bundle_pt bundle, service_registration_pt registration, service_reference_pt *out) {
celix_status_t status = CELIX_SUCCESS;
- *reference = malloc(sizeof(**reference));
- if (!*reference) {
+ service_reference_pt ref = calloc(1, sizeof(*ref));
+ if (!ref) {
status = CELIX_ENOMEM;
} else {
-
- (*reference)->bundle = bundle;
- (*reference)->registration = registration;
+ ref->bundle = bundle;
+ ref->registration = registration;
+ celixThreadMutex_create(&ref->mutex, NULL);
+ ref->refCount = 1;
}
- framework_logIfError(logger, status, NULL, "Cannot create service reference");
+ if (status == CELIX_SUCCESS) {
+ *out = ref;
+ } else {
+ framework_logIfError(logger, status, NULL, "Cannot create service reference");
+ }
return status;
}
-celix_status_t serviceReference_destroy(service_reference_pt *reference) {
- (*reference)->bundle = NULL;
- (*reference)->registration = NULL;
- free(*reference);
- *reference = NULL;
- return CELIX_SUCCESS;
+void serviceReference_retain(service_reference_pt ref) {
+ celixThreadMutex_lock(&ref->mutex);
+ ref->refCount += 1;
+ celixThreadMutex_unlock(&ref->mutex);
+}
+
+void serviceReference_release(service_reference_pt ref) {
+ celixThreadMutex_lock(&ref->mutex);
+ assert(ref->refCount > 0);
+ ref->refCount -= 1;
+ if (ref->refCount == 0) {
+ serviceReference_destroy(ref);
+ } else {
+ celixThreadMutex_unlock(&ref->mutex);
+ }
+}
+
+static void serviceReference_destroy(service_reference_pt ref) {
+ assert(ref->refCount == 0);
+ celixThreadMutex_destroy(&ref->mutex);
+ ref->bundle = NULL;
+ ref->registration = NULL;
+ free(ref);
}
celix_status_t serviceReference_getBundle(service_reference_pt reference, bundle_pt *bundle) {
@@ -109,7 +134,7 @@ celix_status_t serviceReference_invalidate(service_reference_pt reference) {
return CELIX_SUCCESS;
}
-celix_status_t serviceRefernce_isValid(service_reference_pt reference, bool *result) {
+celix_status_t serviceReference_isValid(service_reference_pt reference, bool *result) {
(*result) = reference->registration != NULL;
return CELIX_SUCCESS;
}
@@ -117,22 +142,8 @@ celix_status_t serviceRefernce_isValid(service_reference_pt reference, bool *res
bool serviceReference_isAssignableTo(service_reference_pt reference, bundle_pt requester, char * serviceName) {
bool allow = true;
- bundle_pt provider = reference->bundle;
- if (requester == provider) {
- return allow;
- }
-// wire_pt providerWire = module_getWire(bundle_getCurrentModule(provider), serviceName);
-// wire_pt requesterWire = module_getWire(bundle_getCurrentModule(requester), serviceName);
-//
-// if (providerWire == NULL && requesterWire != NULL) {
-// allow = (bundle_getCurrentModule(provider) == wire_getExporter(requesterWire));
-// } else if (providerWire != NULL && requesterWire != NULL) {
-// allow = (wire_getExporter(providerWire) == wire_getExporter(requesterWire));
-// } else if (providerWire != NULL && requesterWire == NULL) {
-// allow = (wire_getExporter(providerWire) == bundle_getCurrentModule(requester));
-// } else {
-// allow = false;
-// }
+ /*NOTE for now always true. It would be nice to be able to do somechecks if the services are really assignable.
+ */
return allow;
}