Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 8E1B5200B4B for ; Thu, 21 Jul 2016 17:10:38 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 8CD4E160A72; Thu, 21 Jul 2016 15:10:38 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 86F83160A73 for ; Thu, 21 Jul 2016 17:10:37 +0200 (CEST) Received: (qmail 19152 invoked by uid 500); 21 Jul 2016 15:10:36 -0000 Mailing-List: contact commits-help@celix.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@celix.apache.org Delivered-To: mailing list commits@celix.apache.org Received: (qmail 19143 invoked by uid 99); 21 Jul 2016 15:10:36 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 21 Jul 2016 15:10:36 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 98993E1101; Thu, 21 Jul 2016 15:10:36 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: pnoltes@apache.org To: commits@celix.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: celix git commit: CELIX-370: Adds callbacks support for C++ dep man for C service dependencies Date: Thu, 21 Jul 2016 15:10:36 +0000 (UTC) archived-at: Thu, 21 Jul 2016 15:10:38 -0000 Repository: celix Updated Branches: refs/heads/develop f453a4676 -> 84bdb0c0b CELIX-370: Adds callbacks support for C++ dep man for C service dependencies Project: http://git-wip-us.apache.org/repos/asf/celix/repo Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/84bdb0c0 Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/84bdb0c0 Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/84bdb0c0 Branch: refs/heads/develop Commit: 84bdb0c0b6ca1f72532be54d73d10ef5cb767a71 Parents: f453a46 Author: Pepijn Noltes Authored: Thu Jul 21 17:10:06 2016 +0200 Committer: Pepijn Noltes Committed: Thu Jul 21 17:10:06 2016 +0200 ---------------------------------------------------------------------- .../include/celix/dm/ServiceDependency.h | 48 ++++++- .../include/celix/dm/ServiceDependency_Impl.h | 125 +++++++++++++++++++ documents/best_practices/README.md | 1 + .../dm_example_cxx/phase2/include/Phase2Cmp.h | 6 + .../phase2a/src/Phase2aActivator.cc | 3 +- .../dm_example_cxx/phase2a/src/Phase2aCmp.cc | 5 + .../phase2b/src/Phase2bActivator.cc | 3 +- .../dm_example_cxx/phase2b/src/Phase2bCmp.cc | 5 + 8 files changed, 192 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/celix/blob/84bdb0c0/dependency_manager_cxx/include/celix/dm/ServiceDependency.h ---------------------------------------------------------------------- diff --git a/dependency_manager_cxx/include/celix/dm/ServiceDependency.h b/dependency_manager_cxx/include/celix/dm/ServiceDependency.h index 7b635c3..df3f432 100644 --- a/dependency_manager_cxx/include/celix/dm/ServiceDependency.h +++ b/dependency_manager_cxx/include/celix/dm/ServiceDependency.h @@ -70,6 +70,19 @@ namespace celix { namespace dm { template class CServiceDependency : public TypedServiceDependency { + private: + void (T::*setFp)(const void* service) {nullptr}; + void (T::*setFpWithProperties)(const void* service, Properties&& properties) {nullptr}; + + void (T::*addFp)(const void* service) {nullptr}; + void (T::*addFpWithProperties)(const void* service, Properties&& properties) {nullptr}; + + void (T::*removeFp)(const void* service) {nullptr}; + void (T::*removeFpWithProperties)(const void* service, Properties&& properties) {nullptr}; + + void setupCallbacks(); + int invokeCallback(void(T::*fp)(const void*), const void* service); + int invokeCallbackWithProperties(void(T::*fp)(const void*, Properties&&), service_reference_pt ref, const void* service); public: CServiceDependency() : TypedServiceDependency() {}; virtual ~CServiceDependency() = default; @@ -97,11 +110,42 @@ namespace celix { namespace dm { * @return the C service dependency reference for chaining (fluent API) */ CServiceDependency& setStrategy(DependencyUpdateStrategy strategy); + + /** + * Set the set callback for when the service dependency becomes available + * + * @return the C++ service dependency reference for chaining (fluent API) + */ + CServiceDependency& setCallbacks(void (T::*set)(const void* service)); + + /** + * Set the set callback for when the service dependency becomes available + * + * @return the C++ service dependency reference for chaining (fluent API) + */ + CServiceDependency& setCallbacks(void (T::*set)(const void* service, Properties&& properties)); + + /** + * Set the add and remove callback for when the services of service dependency are added or removed. + * + * @return the C++ service dependency reference for chaining (fluent API) + */ + CServiceDependency& setCallbacks( void (T::*add)(const void* service), void (T::*remove)(const void* service)); + + /** + * Set the add and remove callback for when the services of service dependency are added or removed. + * + * @return the C++ service dependency reference for chaining (fluent API) + */ + CServiceDependency& setCallbacks( + void (T::*add)(const void* service, Properties&& properties), + void (T::*remove)(const void* service, Properties&& properties) + ); }; template class ServiceDependency : public TypedServiceDependency { - protected: + private: std::string name {}; std::string filter {}; std::string versionRange {}; @@ -115,7 +159,7 @@ namespace celix { namespace dm { void (T::*removeFp)(I* service) {nullptr}; void (T::*removeFpWithProperties)(I* service, Properties&& properties) {nullptr}; - private: + void setupService(); void setupCallbacks(); int invokeCallback(void(T::*fp)(I*), const void* service); http://git-wip-us.apache.org/repos/asf/celix/blob/84bdb0c0/dependency_manager_cxx/include/celix/dm/ServiceDependency_Impl.h ---------------------------------------------------------------------- diff --git a/dependency_manager_cxx/include/celix/dm/ServiceDependency_Impl.h b/dependency_manager_cxx/include/celix/dm/ServiceDependency_Impl.h index 4f23b61..9300253 100644 --- a/dependency_manager_cxx/include/celix/dm/ServiceDependency_Impl.h +++ b/dependency_manager_cxx/include/celix/dm/ServiceDependency_Impl.h @@ -42,6 +42,131 @@ CServiceDependency& CServiceDependency::setStrategy(DependencyUpdateStrate return *this; } +//set callbacks +template +CServiceDependency& CServiceDependency::setCallbacks(void (T::*set)(const void* service)) { + this->setFp = set; + this->setupCallbacks(); + return *this; +} + +template +CServiceDependency& CServiceDependency::setCallbacks(void (T::*set)(const void* service, Properties&& properties)) { + this->setFpWithProperties = set; + this->setupCallbacks(); + return *this; +} + +//add remove callbacks +template +CServiceDependency& CServiceDependency::setCallbacks( + void (T::*add)(const void* service), + void (T::*remove)(const void* service)) { + this->addFp = add; + this->removeFp = remove; + this->setupCallbacks(); + return *this; +} + +template +CServiceDependency& CServiceDependency::setCallbacks( + void (T::*add)(const void* service, Properties&& properties), + void (T::*remove)(const void* service, Properties&& properties) +) { + this->addFpWithProperties = add; + this->removeFpWithProperties = remove; + this->setupCallbacks(); + return *this; +} + + +template +void CServiceDependency::setupCallbacks() { + + int(*cset)(void*,const void*) {nullptr}; + int(*cadd)(void*, const void*) {nullptr}; + int(*cremove)(void*, const void*) {nullptr}; + + + if (setFp != nullptr) { + cset = [](void* handle, const void*service) -> int { + auto dep = (CServiceDependency*) handle; + return dep->invokeCallback(dep->setFp, service); + }; + } + if (addFp != nullptr) { + cadd = [](void* handle, const void*service) -> int { + auto dep = (CServiceDependency*) handle; + return dep->invokeCallback(dep->addFp, service); + }; + } + if (removeFp != nullptr) { + cremove = [](void* handle, const void*service) -> int { + auto dep = (CServiceDependency*) handle; + return dep->invokeCallback(dep->removeFp, service); + }; + } + + int(*csetWithRef)(void*, service_reference_pt, const void*) {nullptr}; + int(*caddWithRef)(void*, service_reference_pt, const void*) {nullptr}; + int(*cremoveWithRef)(void*, service_reference_pt, const void*) {nullptr}; + + if (setFpWithProperties != nullptr) { + csetWithRef = [](void* handle, service_reference_pt ref, const void* service) -> int { + auto dep = (CServiceDependency*) handle; + return dep->invokeCallbackWithProperties(dep->setFpWithProperties, ref, service); + }; + } + if (addFpWithProperties != nullptr) { + caddWithRef = [](void* handle, service_reference_pt ref, const void* service) -> int { + auto dep = (CServiceDependency*) handle; + return dep->invokeCallbackWithProperties(dep->addFpWithProperties, ref, service); + }; + } + if (removeFpWithProperties != nullptr) { + cremoveWithRef = [](void* handle, service_reference_pt ref, const void* service) -> int { + auto dep = (CServiceDependency*) handle; + return dep->invokeCallbackWithProperties(dep->removeFpWithProperties, ref, service); + }; + } + + serviceDependency_setCallbackHandle(this->cServiceDependency(), this); + serviceDependency_setCallbacks(this->cServiceDependency(), cset, cadd, nullptr, cremove, nullptr); + serviceDependency_setCallbacksWithServiceReference(this->cServiceDependency(), csetWithRef, caddWithRef, nullptr, cremoveWithRef, nullptr); +}; + +template +int CServiceDependency::invokeCallback(void(T::*fp)(const void* service), const void* service) { + T *cmp = this->componentInstance; + (cmp->*fp)(service); + return 0; +}; + +template +int CServiceDependency::invokeCallbackWithProperties(void(T::*fp)(const void*, Properties&&), service_reference_pt ref, const void* service) { + service_registration_pt reg {nullptr}; + properties_pt props {nullptr}; + T *cmp = this->componentInstance; + serviceReference_getServiceRegistration(ref, ®); + serviceRegistration_getProperties(reg, &props); + + Properties properties {}; + const char* key {nullptr}; + const char* value {nullptr}; + + hash_map_iterator_t iter = hashMapIterator_construct((hash_map_pt)props); + while(hashMapIterator_hasNext(&iter)) { + key = (const char*) hashMapIterator_nextKey(&iter); + value = properties_get(props, key); + //std::cout << "got property " << key << "=" << value << "\n"; + properties[key] = value; + } + + (cmp->*fp)(service, static_cast(properties)); //explicit move of lvalue properties. + return 0; +} + + template ServiceDependency::ServiceDependency() : TypedServiceDependency() { setupService(); http://git-wip-us.apache.org/repos/asf/celix/blob/84bdb0c0/documents/best_practices/README.md ---------------------------------------------------------------------- diff --git a/documents/best_practices/README.md b/documents/best_practices/README.md index 9671b2d..1e5ab76 100644 --- a/documents/best_practices/README.md +++ b/documents/best_practices/README.md @@ -94,6 +94,7 @@ The error checking is very minimal in these example to keep the focus on how to ### Bar example + The bar example is a simple component providing the `example` service. ```C http://git-wip-us.apache.org/repos/asf/celix/blob/84bdb0c0/examples/dm_example_cxx/phase2/include/Phase2Cmp.h ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase2/include/Phase2Cmp.h b/examples/dm_example_cxx/phase2/include/Phase2Cmp.h index 4288e3e..ca85cc4 100644 --- a/examples/dm_example_cxx/phase2/include/Phase2Cmp.h +++ b/examples/dm_example_cxx/phase2/include/Phase2Cmp.h @@ -27,13 +27,19 @@ #include #include +extern "C" { +#include "log_service.h" +}; + class Phase2Cmp : public IPhase2 { IPhase1* phase1 {nullptr}; + log_service_pt logSrv {nullptr}; public: Phase2Cmp() = default; virtual ~Phase2Cmp() { std::cout << "Destroying Phase2\n"; }; void setPhase1(IPhase1* phase); //injector used by dependency manager + void setLogService(log_service_pt logSrv); virtual double getData(); //implements IPhase2 private: http://git-wip-us.apache.org/repos/asf/celix/blob/84bdb0c0/examples/dm_example_cxx/phase2a/src/Phase2aActivator.cc ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase2a/src/Phase2aActivator.cc b/examples/dm_example_cxx/phase2a/src/Phase2aActivator.cc index fc6269a..d90b5d0 100644 --- a/examples/dm_example_cxx/phase2a/src/Phase2aActivator.cc +++ b/examples/dm_example_cxx/phase2a/src/Phase2aActivator.cc @@ -43,7 +43,8 @@ void Phase2Activator::init(DependencyManager& manager) { ) .add(createCServiceDependency() .setRequired(false) - .setCService(OSGI_LOGSERVICE_NAME, {}, {}) + .setCService(OSGI_LOGSERVICE_NAME, "", "") + .setCallbacks((void (Phase2Cmp::*)(const void*)) &Phase2Cmp::setLogService) ) ); } http://git-wip-us.apache.org/repos/asf/celix/blob/84bdb0c0/examples/dm_example_cxx/phase2a/src/Phase2aCmp.cc ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase2a/src/Phase2aCmp.cc b/examples/dm_example_cxx/phase2a/src/Phase2aCmp.cc index 088c218..e72a36c 100644 --- a/examples/dm_example_cxx/phase2a/src/Phase2aCmp.cc +++ b/examples/dm_example_cxx/phase2a/src/Phase2aCmp.cc @@ -27,6 +27,11 @@ void Phase2Cmp::setPhase1(IPhase1* phase1) { this->phase1 = phase1; } +void Phase2Cmp::setLogService(log_service_pt logSrv) { + this->logSrv = logSrv; +} + double Phase2Cmp::getData() { + logSrv->log(logSrv->logger, OSGI_LOGSERVICE_DEBUG, (char*)"getting data from phase2cmp A\n"); return phase1->getData() * 42.0; }; http://git-wip-us.apache.org/repos/asf/celix/blob/84bdb0c0/examples/dm_example_cxx/phase2b/src/Phase2bActivator.cc ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase2b/src/Phase2bActivator.cc b/examples/dm_example_cxx/phase2b/src/Phase2bActivator.cc index f518581..c026203 100644 --- a/examples/dm_example_cxx/phase2b/src/Phase2bActivator.cc +++ b/examples/dm_example_cxx/phase2b/src/Phase2bActivator.cc @@ -42,7 +42,8 @@ void Phase2Activator::init(DependencyManager& manager) { ) .add(createCServiceDependency() .setRequired(false) - .setCService(OSGI_LOGSERVICE_NAME, {}, {}) + .setCService(OSGI_LOGSERVICE_NAME, "", "") + .setCallbacks((void (Phase2Cmp::*)(const void*)) &Phase2Cmp::setLogService) ) ); } http://git-wip-us.apache.org/repos/asf/celix/blob/84bdb0c0/examples/dm_example_cxx/phase2b/src/Phase2bCmp.cc ---------------------------------------------------------------------- diff --git a/examples/dm_example_cxx/phase2b/src/Phase2bCmp.cc b/examples/dm_example_cxx/phase2b/src/Phase2bCmp.cc index fac2867..cd6df23 100644 --- a/examples/dm_example_cxx/phase2b/src/Phase2bCmp.cc +++ b/examples/dm_example_cxx/phase2b/src/Phase2bCmp.cc @@ -27,6 +27,11 @@ void Phase2Cmp::setPhase1(IPhase1* phase1) { this->phase1 = phase1; } +void Phase2Cmp::setLogService(log_service_pt logSrv) { + this->logSrv = logSrv; +} + double Phase2Cmp::getData() { + logSrv->log(logSrv->logger, OSGI_LOGSERVICE_DEBUG, (char*)"getting data from phase2cmp B\n"); return phase1->getData() * 24.0; };