27 #include <unordered_map>
31 #include "celix_utils.h"
35 #include "celix/Properties.h"
36 #include "celix/Utils.h"
39 #include "celix/Filter.h"
75 cCtx{std::move(_cCtx)} {}
83 std::lock_guard<std::mutex> lck{
mutex};
91 std::lock_guard<std::mutex> lck{
mutex};
102 long localTrkId = -1;
104 std::lock_guard<std::mutex> lck{
mutex};
112 if (localTrkId >= 0) {
115 std::lock_guard<std::mutex> lck{
mutex};
129 virtual void open() = 0;
137 bool needWaitOpening =
false;
138 bool needWaitClosing =
false;
141 std::lock_guard<std::mutex> lck{
mutex};
144 needWaitOpening =
true;
146 needWaitClosing =
true;
149 if (needWaitOpening) {
152 if (needWaitClosing) {
169 return [](T *tracker) {
189 "celix::AbstractTracker delete callback",
201 const std::shared_ptr<celix_bundle_context_t>
cCtx;
219 #if __cplusplus >= 201703L //C++17 or higher
221 std::string_view _svcVersionRange, celix::Filter _filter) :
AbstractTracker{std::move(_cCtx)},
svcName{_svcName},
223 setupServiceTrackerOptions();
227 std::string _svcVersionRange, celix::Filter _filter) :
AbstractTracker{std::move(_cCtx)},
svcName{std::move(_svcName)},
229 setupServiceTrackerOptions();
239 std::lock_guard<std::mutex> lck{
mutex};
283 void setupServiceTrackerOptions() {
284 opts.trackerCreatedCallbackData =
this;
288 std::lock_guard<std::mutex> callbackLock{trk->
mutex};
322 #if __cplusplus >= 201703L //C++17 or higher
323 static std::shared_ptr<ServiceTracker<I>>
create(
324 std::shared_ptr<celix_bundle_context_t>
cCtx,
328 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
setCallbacks,
329 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
addCallbacks,
330 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
remCallbacks) {
331 auto tracker = std::shared_ptr<ServiceTracker<I>>{
340 AbstractTracker::delCallback<ServiceTracker<I>>()};
345 static std::shared_ptr<ServiceTracker<I>>
create(
346 std::shared_ptr<celix_bundle_context_t>
cCtx,
350 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
setCallbacks,
351 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
addCallbacks,
352 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
remCallbacks) {
353 auto tracker = std::shared_ptr<ServiceTracker<I>>{
362 AbstractTracker::delCallback<ServiceTracker<I>>()};
378 std::shared_ptr<I> result{};
379 std::lock_guard<std::mutex> lck{
mutex};
397 std::vector<std::shared_ptr<I>> result{};
398 std::lock_guard<std::mutex> lck{
mutex};
399 result.reserve(
entries.size());
401 result.push_back(e->svc);
407 SvcEntry(
long _svcId,
long _svcRanking, std::shared_ptr<I> _svc,
408 std::shared_ptr<const celix::Properties> _properties,
409 std::shared_ptr<const celix::Bundle> _owner) :
svcId(_svcId),
svcRanking(_svcRanking),
410 svc(std::move(_svc)),
412 owner(std::move(_owner)) {}
417 std::shared_ptr<const celix::Bundle>
owner;
420 #if __cplusplus >= 201703L //C++17 or higher
421 ServiceTracker(std::shared_ptr<celix_bundle_context_t> _cCtx, std::string_view _svcName,
422 std::string_view _svcVersionRange, celix::Filter _filter,
423 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>> _setCallbacks,
424 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>> _addCallbacks,
425 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>> _remCallbacks) :
430 setupServiceTrackerOptions();
433 ServiceTracker(std::shared_ptr<celix_bundle_context_t> _cCtx, std::string _svcName,
434 std::string _svcVersionRange, celix::Filter _filter,
435 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>> _setCallbacks,
436 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>> _addCallbacks,
437 std::vector<std::function<
void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>> _remCallbacks) :
438 GenericServiceTracker{std::move(_cCtx), std::move(_svcName), std::move(_svcVersionRange), std::move(_filter)},
442 setupServiceTrackerOptions();
446 static std::shared_ptr<SvcEntry>
createEntry(
void* voidSvc,
const celix_properties_t* cProps,
const celix_bundle_t* cBnd) {
447 long svcId = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_ID, -1L);
448 long svcRanking = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_RANKING, 0);
449 auto svc = std::shared_ptr<I>{
static_cast<I*
>(voidSvc), [](I*){}};
450 auto props = celix::Properties::wrap(cProps);
451 auto owner = std::make_shared<celix::Bundle>(
const_cast<celix_bundle_t*
>(cBnd));
452 return std::make_shared<SvcEntry>(svcId, svcRanking, svc, props, owner);
457 std::weak_ptr<void> svcObserve = entry->svc;
458 std::weak_ptr<const celix::Properties> propsObserve = entry->properties;
459 std::weak_ptr<const celix::Bundle> ownerObserve = entry->owner;
460 entry->svc =
nullptr;
461 entry->properties =
nullptr;
462 entry->owner =
nullptr;
465 waitForExpired(ownerObserve, entry->svcId,
"service bundle (owner)");
471 auto start = std::chrono::system_clock::now();
472 while (!observe.expired()) {
473 auto now = std::chrono::system_clock::now();
474 auto durationInMilli = std::chrono::duration_cast<std::chrono::milliseconds>(now - start);
476 celix_bundleContext_log(
cCtx.get(), CELIX_LOG_LEVEL_WARNING,
"Cannot remove %s associated with service.id %li, because it is still in use. Current shared_ptr use count is %i\n", objName, svcId, (
int)observe.use_count());
479 std::this_thread::sleep_for(std::chrono::milliseconds{50});
485 std::vector<std::shared_ptr<I>> updateVector{};
487 std::lock_guard<std::mutex> lck{
mutex};
488 updateVector.reserve(
entries.size());
489 for (
const auto &entry :
entries) {
490 updateVector.push_back(entry->svc);
498 std::vector<std::pair<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>>> updateVector{};
499 updateVector.reserve(
entries.size());
501 std::lock_guard<std::mutex> lck{
mutex};
502 for (
const auto &entry :
entries) {
503 updateVector.emplace_back(entry->svc, entry->properties);
511 std::vector<std::tuple<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>, std::shared_ptr<const celix::Bundle>>> updateVector{};
512 updateVector.reserve(
entries.size());
514 std::lock_guard<std::mutex> lck{
mutex};
515 for (
const auto &entry :
entries) {
516 updateVector.emplace_back(entry->svc, entry->properties, entry->owner);
527 const std::vector<std::function<void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
setCallbacks;
528 const std::vector<std::function<void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
addCallbacks;
529 const std::vector<std::function<void(
const std::shared_ptr<I>&,
const std::shared_ptr<const celix::Properties>&,
const std::shared_ptr<const celix::Bundle>&)>>
remCallbacks;
532 const std::vector<std::function<void(
const std::vector<std::shared_ptr<I>>)>>
updateCallbacks{};
533 const std::vector<std::function<void(
const std::vector<std::pair<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>>>)>>
updateWithPropertiesCallbacks{};
534 const std::vector<std::function<void(
const std::vector<std::tuple<std::shared_ptr<I>, std::shared_ptr<const celix::Properties>, std::shared_ptr<const celix::Bundle>>>)>>
updateWithOwnerCallbacks{};
537 bool operator() (
const std::shared_ptr<SvcEntry>& a,
const std::shared_ptr<SvcEntry>& b)
const {
538 int cmp = celix_utils_compareServiceIdsAndRanking(a->svcId, a->svcRanking, b->svcId, b->svcRanking);
549 void setupServiceTrackerOptions() {
553 opts.callbackHandle =
this;
554 opts.
addWithOwner = [](
void *handle,
void *voidSvc,
const celix_properties_t* cProps,
const celix_bundle_t* cBnd) {
558 std::lock_guard<std::mutex> lck{tracker->mutex};
559 tracker->entries.insert(entry);
560 tracker->cachedEntries[entry->svcId] = entry;
562 tracker->
svcCount.fetch_add(1, std::memory_order_relaxed);
563 for (
const auto& cb : tracker->addCallbacks) {
564 cb(entry->svc, entry->properties, entry->owner);
566 tracker->invokeUpdateCallbacks();
568 opts.
removeWithOwner = [](
void *handle,
void*,
const celix_properties_t* cProps,
const celix_bundle_t*) {
569 auto tracker =
static_cast<ServiceTracker<I>*
>(handle);
570 long svcId = celix_properties_getAsLong(cProps, OSGI_FRAMEWORK_SERVICE_ID, -1L);
571 std::shared_ptr<SvcEntry> entry{};
573 std::lock_guard<std::mutex> lck{tracker->
mutex};
574 auto it = tracker->cachedEntries.find(svcId);
575 assert(it != tracker->cachedEntries.end());
578 tracker->entries.erase(entry);
580 for (
const auto& cb : tracker->remCallbacks) {
581 cb(entry->svc, entry->properties, entry->owner);
583 tracker->invokeUpdateCallbacks();
584 tracker->svcCount.fetch_sub(1, std::memory_order_relaxed);
585 tracker->waitForExpiredSvcEntry(entry);
587 opts.
setWithOwner = [](
void *handle,
void *voidSvc,
const celix_properties_t *cProps,
const celix_bundle_t *cBnd) {
588 auto tracker =
static_cast<ServiceTracker<I>*
>(handle);
589 std::unique_lock<std::mutex> lck{tracker->mutex};
590 auto prevEntry = tracker->highestRankingServiceEntry;
592 tracker->highestRankingServiceEntry =
createEntry(voidSvc, cProps, cBnd);
594 tracker->highestRankingServiceEntry =
nullptr;
596 for (
const auto& cb : tracker->setCallbacks) {
597 if (tracker->highestRankingServiceEntry) {
598 auto& e = tracker->highestRankingServiceEntry;
599 cb(e->svc, e->properties, e->owner);
601 cb(
nullptr,
nullptr,
nullptr);
605 tracker->waitForExpiredSvcEntry(prevEntry);
627 static std::shared_ptr<BundleTracker>
create(
628 std::shared_ptr<celix_bundle_context_t>
cCtx,
629 bool includeFrameworkBundle,
630 std::vector<std::function<
void(
const celix::Bundle&)>> onInstallCallbacks,
631 std::vector<std::function<
void(
const celix::Bundle&)>> onStartCallbacks,
632 std::vector<std::function<
void(
const celix::Bundle&)>> onStopCallbacks) {
634 auto tracker = std::shared_ptr<BundleTracker>{
637 includeFrameworkBundle,
638 std::move(onInstallCallbacks),
639 std::move(onStartCallbacks),
640 std::move(onStopCallbacks)},
641 AbstractTracker::delCallback<BundleTracker>()};
650 std::lock_guard<std::mutex> lck{
mutex};
662 std::shared_ptr<celix_bundle_context_t> _cCtx,
663 bool _includeFrameworkBundle,
664 std::vector<std::function<
void(
const celix::Bundle&)>> _onInstallCallbacks,
665 std::vector<std::function<
void(
const celix::Bundle&)>> _onStartCallbacks,
666 std::vector<std::function<
void(
const celix::Bundle&)>> _onStopCallbacks) :
668 includeFrameworkBundle{_includeFrameworkBundle},
669 onInstallCallbacks{std::move(_onInstallCallbacks)},
670 onStartCallbacks{std::move(_onStartCallbacks)},
671 onStopCallbacks{std::move(_onStopCallbacks)} {
674 opts.includeFrameworkBundle = includeFrameworkBundle;
675 opts.callbackHandle =
this;
676 opts.
onInstalled = [](
void *handle,
const celix_bundle_t *cBnd) {
677 auto tracker =
static_cast<BundleTracker *
>(handle);
679 for (
const auto& cb : tracker->onInstallCallbacks) {
683 opts.
onStarted = [](
void *handle,
const celix_bundle_t *cBnd) {
684 auto tracker =
static_cast<BundleTracker *
>(handle);
686 for (
const auto& cb : tracker->onStartCallbacks) {
690 opts.
onStopped = [](
void *handle,
const celix_bundle_t *cBnd) {
691 auto tracker =
static_cast<BundleTracker *
>(handle);
693 for (
const auto& cb : tracker->onStopCallbacks) {
697 opts.trackerCreatedCallbackData =
this;
699 auto* trk =
static_cast<BundleTracker*
>(data);
700 std::lock_guard<std::mutex> callbackLock{trk->mutex};
705 const bool includeFrameworkBundle;
706 const std::vector<std::function<void(
const celix::Bundle&)>> onInstallCallbacks;
707 const std::vector<std::function<void(
const celix::Bundle&)>> onStartCallbacks;
708 const std::vector<std::function<void(
const celix::Bundle&)>> onStopCallbacks;
753 #if __cplusplus >= 201703L //C++17 or higher
754 static std::shared_ptr<MetaTracker>
create(
755 std::shared_ptr<celix_bundle_context_t>
cCtx,
756 std::string_view serviceName,
759 auto tracker = std::shared_ptr<MetaTracker>{
762 std::string{serviceName},
763 std::move(onTrackerCreated),
764 std::move(onTrackerDestroyed)},
765 AbstractTracker::delCallback<MetaTracker>()};
770 static std::shared_ptr<MetaTracker>
create(
771 std::shared_ptr<celix_bundle_context_t>
cCtx,
772 std::string serviceName,
775 auto tracker = std::shared_ptr<MetaTracker>{
778 std::move(serviceName),
779 std::move(onTrackerCreated),
780 std::move(onTrackerDestroyed)},
781 AbstractTracker::delCallback<MetaTracker>()};
791 std::lock_guard<std::mutex> lck{
mutex};
798 serviceName.empty() ?
nullptr : serviceName.c_str(),
799 static_cast<void*
>(
this),
801 auto *trk = static_cast<MetaTracker *>(handle);
802 std::string svcName = cInfo->serviceName == nullptr ?
"" : cInfo->serviceName;
803 ServiceTrackerInfo info{svcName, celix::Filter::wrap(cInfo->filter), cInfo->bundleId};
804 for (
const auto& cb : trk->onTrackerCreated) {
810 std::string svcName = cInfo->serviceName ==
nullptr ?
"" : cInfo->serviceName;
811 ServiceTrackerInfo info{svcName, celix::Filter::wrap(cInfo->filter), cInfo->bundleId};
812 for (
const auto& cb : trk->onTrackerDestroyed) {
816 static_cast<void*
>(
this),
819 std::lock_guard<std::mutex> callbackLock{trk->
mutex};
830 std::shared_ptr<celix_bundle_context_t> _cCtx,
831 std::string _serviceName,
832 std::vector<std::function<
void(
const ServiceTrackerInfo&)>> _onTrackerCreated,
833 std::vector<std::function<
void(
const ServiceTrackerInfo&)>> _onTrackerDestroyed) :
834 AbstractTracker{std::move(_cCtx)},
835 serviceName{std::move(_serviceName)},
836 onTrackerCreated{std::move(_onTrackerCreated)},
837 onTrackerDestroyed{std::move(_onTrackerDestroyed)} {}
839 const std::string serviceName;
840 const std::vector<std::function<void(
const ServiceTrackerInfo&)>> onTrackerCreated;
841 const std::vector<std::function<void(
const ServiceTrackerInfo&)>> onTrackerDestroyed;