Apache Celix  latest
Apache Celix is a framework for C, C++14 and C++17 to develop dynamic modular software applications using component and in-process service-oriented programming.
BundleActivator.h
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #pragma once
21 
22 #include <memory>
23 
25 #include "celix_bundle_activator.h"
26 
27 #if __cplusplus >= 201402L //C++14 or higher
28 #include "celix/BundleContext.h"
29 namespace celix {
30 namespace impl {
31  template<typename I>
33  long bndId{};
34  std::shared_ptr<celix::BundleContext> ctx;
35  std::unique_ptr<I> bundleActivator;
36  };
37 
38  template<typename I>
39  typename std::enable_if<std::is_constructible<I, std::shared_ptr<celix::BundleContext>>::value, celix_status_t>::type
40  createActivator(celix_bundle_context_t * cCtx, void * *out) {
41  auto ctx = std::make_shared<celix::BundleContext>(cCtx);
42  auto act = std::make_unique<I>(ctx);
43  auto *data = new BundleActivatorData<I>{ctx->getBundleId(), std::move(ctx), std::move(act)};
44  *out = (void *) data;
45  return CELIX_SUCCESS;
46  }
47 
48  template<typename I>
49  typename std::enable_if<std::is_constructible<I, std::shared_ptr<celix::dm::DependencyManager>>::value, celix_status_t>::type
50  createActivator(celix_bundle_context_t * cCtx, void * *out) {
51  auto ctx = std::make_shared<celix::BundleContext>(cCtx);
52  auto dm = ctx->getDependencyManager();
53  auto act = std::make_unique<I>(dm);
54  dm->start();
55  auto *data = new BundleActivatorData<I>{ctx->getBundleId(), std::move(ctx), std::move(act)};
56  *out = (void *) data;
57  return CELIX_SUCCESS;
58  }
59 
60  template<typename T>
61  void waitForExpired(long bndId, std::weak_ptr<celix::BundleContext> &weakCtx, const char *name,
62  std::weak_ptr<T> &observe) {
63  auto start = std::chrono::steady_clock::now();
64  while (!observe.expired()) {
65  auto now = std::chrono::steady_clock::now();
66  auto durationInSec = std::chrono::duration_cast<std::chrono::seconds>(now - start);
67  if (durationInSec > std::chrono::seconds{5}) {
68  auto msg = std::string{"Cannot destroy bundle "} + std::to_string(bndId) + ". " + name +
69  " is still in use. std::shared_ptr use count is " + std::to_string(observe.use_count()) +
70  "\n";
71  auto ctx = weakCtx.lock();
72  if (ctx) {
73  ctx->logWarn("%s", msg.c_str());
74  } else {
75  std::cout << msg;
76  }
77  start = now;
78  }
79  std::this_thread::sleep_for(std::chrono::milliseconds{50});
80  }
81  }
82 
83  template<typename I>
84  celix_status_t destroyActivator(void *userData) {
85  auto *data = static_cast<BundleActivatorData<I> *>(userData);
86  data->bundleActivator.reset();
87  data->ctx->getDependencyManager()->clear();
88 
89  auto bndId = data->bndId;
90  std::weak_ptr<celix::BundleContext> ctx = data->ctx;
91  std::weak_ptr<celix::dm::DependencyManager> dm = data->ctx->getDependencyManager();
92  delete data;
93  waitForExpired(bndId, ctx, "celix::BundleContext", ctx);
94  waitForExpired(bndId, ctx, "celix::dm::DependencyManager", dm);
95  return CELIX_SUCCESS;
96  }
97 }}
98 #else //C++11
99 namespace celix {
100 namespace impl {
101  template<typename I>
102  struct BundleActivatorData {
103  std::shared_ptr<celix::dm::DependencyManager> dm;
104  std::unique_ptr<I> bundleActivator;
105  };
106 
107  template<typename I>
108  typename std::enable_if<std::is_constructible<I, std::shared_ptr<celix::dm::DependencyManager>>::value, celix_status_t>::type
109  createActivator(celix_bundle_context_t *cCtx, void **out) {
110  auto dm = std::make_shared<celix::dm::DependencyManager>(cCtx);
111  auto act = std::unique_ptr<I>(new I{dm});
112  dm->start();
113  auto *data = new BundleActivatorData<I>{std::move(dm), std::move(act)};
114  *out = (void *) data;
115  return CELIX_SUCCESS;
116  }
117 
118  template<typename I>
119  celix_status_t destroyActivator(void *userData) {
120  auto *data = static_cast<BundleActivatorData<I> *>(userData);
121  data->bundleActivator.reset();
122  data->dm->clear();
123  delete data;
124  return CELIX_SUCCESS;
125  }
126 } //end namespace impl
127 } //end namespace celix
128 #endif
129 
149 #define CELIX_GEN_CXX_BUNDLE_ACTIVATOR(actType) \
150 extern "C" celix_status_t celix_bundleActivator_create(celix_bundle_context_t *context, void** userData) { \
151  return celix::impl::createActivator<actType>(context, userData); \
152 } \
153  \
154 extern "C" celix_status_t celix_bundleActivator_start(void *, celix_bundle_context_t *) { \
155  /*nop*/ \
156  return CELIX_SUCCESS; \
157 } \
158  \
159 extern "C" celix_status_t celix_bundleActivator_stop(void *userData, celix_bundle_context_t*) { \
160  return celix::impl::destroyActivator<actType>(userData); \
161 } \
162  \
163 extern "C" celix_status_t celix_bundleActivator_destroy(void *, celix_bundle_context_t*) { \
164  /*nop*/ \
165  return CELIX_SUCCESS; \
166 }
celix::impl::BundleActivatorData
Definition: BundleActivator.h:32
celix
Definition: Bundle.h:28
celix::impl::BundleActivatorData::bundleActivator
std::unique_ptr< I > bundleActivator
Definition: BundleActivator.h:35
celix::impl::waitForExpired
void waitForExpired(long bndId, std::weak_ptr< celix::BundleContext > &weakCtx, const char *name, std::weak_ptr< T > &observe)
Definition: BundleActivator.h:61
BundleContext.h
celix::impl::BundleActivatorData::ctx
std::shared_ptr< celix::BundleContext > ctx
Definition: BundleActivator.h:34
celix::impl::createActivator
std::enable_if< std::is_constructible< I, std::shared_ptr< celix::BundleContext > >::value, celix_status_t >::type createActivator(celix_bundle_context_t *cCtx, void **out)
Definition: BundleActivator.h:40
DependencyManager.h
celix_bundle_activator.h
celix::impl::destroyActivator
celix_status_t destroyActivator(void *userData)
Definition: BundleActivator.h:84
celix::impl::BundleActivatorData::bndId
long bndId
Definition: BundleActivator.h:33