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.
DependencyManager_Impl.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 #include <cassert>
21 #include "DependencyManager.h"
22 
23 using namespace celix::dm;
24 
25 inline DependencyManager::DependencyManager(celix_bundle_context_t *ctx) :
26  context{ctx, [](celix_bundle_context_t*){/*nop*/}},
27  cDepMan{celix_bundleContext_getDependencyManager(ctx), [](celix_dependency_manager_t*){/*nop*/}} {}
28 
30  clearAsync();
31 }
32 
33 template<class T>
34 Component<T>& DependencyManager::createComponentInternal(std::string name, std::string uuid) {
35  auto cmp = Component<T>::create(this->context.get(), this->cDepMan.get(), std::move(name), std::move(uuid));
36  if (cmp->isValid()) {
37  auto baseCmp = std::static_pointer_cast<BaseComponent>(cmp);
38  std::lock_guard<std::mutex> lck{mutex};
39  this->components.push_back(baseCmp);
40  }
41 
42  return *cmp;
43 }
44 
45 template<class T>
46 inline
47 typename std::enable_if<std::is_default_constructible<T>::value, Component<T>&>::type
48 DependencyManager::createComponent(std::string name, std::string uuid) {
49  return createComponentInternal<T>(std::move(name), std::move(uuid));
50 }
51 
52 template<class T>
53 Component<T>& DependencyManager::createComponent(std::unique_ptr<T>&& rhs, std::string name, std::string uuid) {
54  return createComponentInternal<T>(std::move(name), std::move(uuid)).setInstance(std::move(rhs));
55 }
56 
57 template<class T>
58 Component<T>& DependencyManager::createComponent(std::shared_ptr<T> rhs, std::string name, std::string uuid) {
59  return createComponentInternal<T>(std::move(name), std::move(uuid)).setInstance(rhs);
60 }
61 
62 template<class T>
63 Component<T>& DependencyManager::createComponent(T rhs, std::string name, std::string uuid) {
64  return createComponentInternal<T>(std::move(name), std::move(uuid)).setInstance(std::forward<T>(rhs));
65 }
66 
67 inline void DependencyManager::start() {
68  build();
69 }
70 
71 inline void DependencyManager::build() {
72  buildAsync();
73  wait();
74 }
75 
77  std::lock_guard<std::mutex> lck{mutex};
78  for (auto& cmp : components) {
79  cmp->runBuild();
80  }
81 }
82 
84  removeComponent(component.getUUID());
85 }
86 
87 inline bool DependencyManager::removeComponent(const std::string& uuid) {
88  bool removed = removeComponentAsync(uuid);
89  wait();
90  return removed;
91 }
92 
93 inline bool DependencyManager::removeComponentAsync(const std::string& uuid) {
94  std::shared_ptr<BaseComponent> tmpStore{};
95  {
96  std::lock_guard<std::mutex> lck{mutex};
97  for (auto it = components.begin(); it != components.end(); ++it) {
98  if ( (*it)->getUUID() == uuid) {
99  //found
100  tmpStore = *it; //prevents destruction in lock
101  components.erase(it);
102  break;
103  }
104  }
105  }
106  return tmpStore != nullptr;
107 }
108 
110  clearAsync();
111  wait();
112 }
113 
115  std::vector<std::shared_ptr<BaseComponent>> swappedComponents{};
116  {
117  std::lock_guard<std::mutex> lck{mutex};
118  std::swap(swappedComponents, components);
119  }
120  swappedComponents.clear();
121 }
122 
123 inline void DependencyManager::wait() const {
124  celix_dependencyManager_wait(cDepMan.get());
125 }
126 
127 inline void DependencyManager::waitIfAble() const {
128  auto* fw = celix_bundleContext_getFramework(context.get());
130  celix_dependencyManager_wait(cDepMan.get());
131  }
132 }
133 
134 inline void DependencyManager::stop() {
135  clear();
136 }
137 
138 inline std::size_t DependencyManager::getNrOfComponents() const {
139  return celix_dependencyManager_nrOfComponents(cDepMan.get());
140 }
141 
142 template<typename T>
143 inline std::shared_ptr<Component<T>> DependencyManager::findComponent(const std::string& uuid) const {
144  std::lock_guard<std::mutex> lck{mutex};
145  std::shared_ptr<BaseComponent> found{nullptr};
146  for (const auto& cmp : components) {
147  if (cmp->getUUID() == uuid) {
148  found = cmp;
149  }
150  }
151  if (found) {
152  return std::static_pointer_cast<Component<T>>(found);
153  } else {
154  return nullptr;
155  }
156 }
157 
158 static celix::dm::DependencyManagerInfo createDepManInfoFromC(celix_dependency_manager_info_t* cInfo) {
160  info.bndId = cInfo->bndId;
161  info.bndSymbolicName = std::string{cInfo->bndSymbolicName};
162 
163  for (int i = 0; i < celix_arrayList_size(cInfo->components); ++i) {
164  auto* cCmpInfo = static_cast<dm_component_info_t*>(celix_arrayList_get(cInfo->components, i));
165  celix::dm::ComponentInfo cmpInfo{};
166  cmpInfo.uuid = std::string{cCmpInfo->id};
167  cmpInfo.name = std::string{cCmpInfo->name};
168  cmpInfo.isActive = cCmpInfo->active;
169  cmpInfo.state = std::string{cCmpInfo->state};
170  cmpInfo.nrOfTimesStarted = cCmpInfo->nrOfTimesStarted;
171  cmpInfo.nrOfTimesResumed = cCmpInfo->nrOfTimesResumed;
172 
173  for (int k = 0; k < celix_arrayList_size(cCmpInfo->interfaces); ++k) {
174  auto* cIntInfo = static_cast<dm_interface_info_t*>(celix_arrayList_get(cCmpInfo->interfaces, k));
175  celix::dm::InterfaceInfo intInfo{};
176  intInfo.serviceName = std::string{cIntInfo->name};
177  CELIX_PROPERTIES_ITERATE(cIntInfo->properties, iter) {
178  intInfo.properties[std::string{iter.key}] = std::string{iter.entry.value};
179  }
180  cmpInfo.interfacesInfo.emplace_back(std::move(intInfo));
181  }
182 
183  for (int k = 0; k < celix_arrayList_size(cCmpInfo->dependency_list); ++k) {
184  auto *cDepInfo = static_cast<dm_service_dependency_info_t *>(celix_arrayList_get(cCmpInfo->dependency_list, k));
186  depInfo.serviceName = std::string{cDepInfo->serviceName == nullptr ? "" : cDepInfo->serviceName};
187  depInfo.filter = std::string{cDepInfo->filter == nullptr ? "" : cDepInfo->filter};
188  depInfo.versionRange = std::string{cDepInfo->versionRange == nullptr ? "" : cDepInfo->versionRange};
189  depInfo.isAvailable = cDepInfo->available;
190  depInfo.isRequired = cDepInfo->required;
191  depInfo.nrOfTrackedServices = cDepInfo->count;
192  cmpInfo.dependenciesInfo.emplace_back(std::move(depInfo));
193  }
194 
195  info.components.emplace_back(std::move(cmpInfo));
196  }
197  return info;
198 }
199 
201  auto* cInfo = celix_dependencyManager_createInfo(cDependencyManager(), celix_bundleContext_getBundleId(context.get()));
202  if (cInfo) {
203  auto result = createDepManInfoFromC(cInfo);
204  celix_dependencyManager_destroyInfo(cDependencyManager(), cInfo);
205  return result;
206  } else {
207  return {};
208  }
209 }
210 
211 inline std::vector<celix::dm::DependencyManagerInfo> DependencyManager::getInfos() const {
212  std::vector<celix::dm::DependencyManagerInfo> result{};
213  auto* cInfos = celix_dependencyManager_createInfos(cDependencyManager());
214  for (int i = 0; i < celix_arrayList_size(cInfos); ++i) {
215  auto* cInfo = static_cast<celix_dependency_manager_info_t*>(celix_arrayList_get(cInfos, i));
216  result.emplace_back(createDepManInfoFromC(cInfo));
217  }
218  celix_dependencyManager_destroyInfos(cDependencyManager(), cInfos);
219  return result;
220 }
221 
222 std::ostream& celix::dm::operator<<(std::ostream &out, const DependencyManager &mng) {
223  char* buf = nullptr;
224  size_t bufSize = 0;
225  FILE* stream = open_memstream(&buf, &bufSize);
226  celix_dependencyManager_printInfo(mng.cDepMan.get(), true, true, stream);
227  fclose(stream);
228  out << buf;
229  free(buf);
230  return out;
231 }
celix::dm::DependencyManager::removeComponent
bool removeComponent(const std::string &uuid)
Removes component with provided UUID from the dependency manager and wail until the component is dest...
Definition: DependencyManager_Impl.h:87
celix::dm::DependencyManager
Definition: DependencyManager.h:47
celix_bundleContext_getBundleId
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_getBundleId(const celix_bundle_context_t *ctx)
Returns the bundle if for the bundle of this bundle context.
celix::dm::ServiceDependencyInfo
Definition: DependencyManagerInfo.h:46
celix::dm::DependencyManager::wait
void wait() const
Wait for an empty Celix event queue.
Definition: DependencyManager_Impl.h:123
celix::dm::DependencyManager::start
void start()
Definition: DependencyManager_Impl.h:67
celix_dm_service_dependency_info_struct
Definition: celix_dm_info.h:41
celix::dm::ServiceDependencyInfo::serviceName
std::string serviceName
Definition: DependencyManagerInfo.h:50
celix::dm::operator<<
std::ostream & operator<<(std::ostream &out, const BaseComponent &cmp)
Definition: Component_Impl.h:54
celix::dm::ComponentInfo
Definition: DependencyManagerInfo.h:81
celix::dm::DependencyManager::waitIfAble
void waitIfAble() const
Wait (if not called on the Celix event thread) for an empty Celix event queue.
Definition: DependencyManager_Impl.h:127
celix_bundleContext_getDependencyManager
CELIX_FRAMEWORK_EXPORT celix_dependency_manager_t * celix_bundleContext_getDependencyManager(celix_bundle_context_t *ctx)
Gets the dependency manager for this bundle context.
celix::dm::DependencyManager::getInfo
celix::dm::DependencyManagerInfo getInfo() const
Definition: DependencyManager_Impl.h:200
celix::dm::DependencyManager::stop
void stop()
Definition: DependencyManager_Impl.h:134
celix::dm::DependencyManager::build
void build()
Definition: DependencyManager_Impl.h:71
celix::dm::DependencyManager::buildAsync
void buildAsync()
Definition: DependencyManager_Impl.h:76
celix_dm_dependency_manager_info_struct::components
celix_array_list_t * components
Definition: celix_dm_info.h:72
celix::dm::DependencyManager::destroyComponent
void destroyComponent(BaseComponent &component)
Removes a component from the Dependency Manager and wait until the component is destroyed.
Definition: DependencyManager_Impl.h:83
celix::dm::DependencyManager::findComponent
std::shared_ptr< Component< T > > findComponent(const std::string &uuid) const
Definition: DependencyManager_Impl.h:143
celix::dm::Component
Definition: Component.h:166
celix::dm::Component::create
static std::shared_ptr< Component< T > > create(celix_bundle_context_t *, celix_dependency_manager_t *cDepMan, std::string name, std::string uuid)
Definition: Component_Impl.h:184
celix::dm::DependencyManager::~DependencyManager
virtual ~DependencyManager()
Definition: DependencyManager_Impl.h:29
celix::dm::DependencyManager::getInfos
std::vector< celix::dm::DependencyManagerInfo > getInfos() const
Definition: DependencyManager_Impl.h:211
celix_framework_isCurrentThreadTheEventLoop
CELIX_FRAMEWORK_EXPORT bool celix_framework_isCurrentThreadTheEventLoop(celix_framework_t *fw)
Returns whether the current thread is the Celix framework event loop thread.
celix::dm::ComponentInfo::uuid
std::string uuid
Definition: DependencyManagerInfo.h:85
celix::dm::InterfaceInfo
Definition: DependencyManagerInfo.h:31
celix::dm::DependencyManager::getNrOfComponents
std::size_t getNrOfComponents() const
Definition: DependencyManager_Impl.h:138
celix::dm::BaseComponent::getUUID
const std::string & getUUID() const
Definition: Component.h:84
celix::dm::DependencyManager::clearAsync
void clearAsync()
Definition: DependencyManager_Impl.h:114
celix_dm_dependency_manager_info_struct
Definition: celix_dm_info.h:69
celix::dm::InterfaceInfo::serviceName
std::string serviceName
Definition: DependencyManagerInfo.h:35
celix::dm::DependencyManager::removeComponentAsync
bool removeComponentAsync(const std::string &uuid)
Removes a component from the Dependency Manager and destroys it async.
Definition: DependencyManager_Impl.h:93
DependencyManager.h
celix::dm::DependencyManager::cDependencyManager
celix_dependency_manager_t * cDependencyManager() const
Definition: DependencyManager.h:60
celix_dm_component_info_struct
Definition: celix_dm_info.h:53
celix::dm::DependencyManager::clear
void clear()
Clears the dependency manager, which removes all configured components and waits until all components...
Definition: DependencyManager_Impl.h:109
celix::dm::DependencyManager::createComponent
std::enable_if< std::is_default_constructible< T >::value, Component< T > & >::type createComponent(std::string name=std::string{}, std::string uuid={})
Definition: DependencyManager_Impl.h:48
celix_dm_dependency_manager_info_struct::bndSymbolicName
char * bndSymbolicName
Definition: celix_dm_info.h:71
celix_dm_dependency_manager_info_struct::bndId
long bndId
Definition: celix_dm_info.h:70
celix::dm
Definition: Component.h:42
celix_dm_interface_info_struct
Definition: celix_dm_info.h:33
celix::dm::DependencyManager::DependencyManager
DependencyManager(celix_bundle_context_t *ctx)
Definition: DependencyManager_Impl.h:25
celix_bundleContext_getFramework
CELIX_FRAMEWORK_EXPORT celix_framework_t * celix_bundleContext_getFramework(const celix_bundle_context_t *ctx)
celix::dm::BaseComponent
Definition: Component.h:58
celix::dm::DependencyManagerInfo
Definition: DependencyManagerInfo.h:126
celix::dm::DependencyManagerInfo::bndId
long bndId
Definition: DependencyManagerInfo.h:130