diff options
author | Lutz Bichler <Lutz.Bichler@bmw.de> | 2019-07-22 12:12:02 +0200 |
---|---|---|
committer | Lutz Bichler <Lutz.Bichler@bmw.de> | 2019-07-22 12:12:02 +0200 |
commit | 99ebf3461f51e4899f06457d6aafdaa4adecd278 (patch) | |
tree | e41d0fbc8682601c80ce9a892f77a8fa355721db | |
parent | 2fd0625d21f1fa8e6a3adfc89ce9f381a4d33990 (diff) | |
download | genivi-common-api-runtime-99ebf3461f51e4899f06457d6aafdaa4adecd278.tar.gz |
capicxx-core-runtime 3.1.12.63.1.12.6
-rw-r--r-- | CHANGES | 6 | ||||
-rw-r--r-- | include/CommonAPI/Event.hpp | 87 | ||||
-rw-r--r-- | include/CommonAPI/Variant.hpp | 15 |
3 files changed, 51 insertions, 57 deletions
@@ -1,6 +1,12 @@ Changes ======= +v3.1.12.6 +- Fix race condition leading to event delivery after unsubscription + +v3.1.12.5 +- Initialize valueType in copy ctors of Variant class + v3.1.12.4 - Fix calling of registered subscription status handlers for selective broadcasts diff --git a/include/CommonAPI/Event.hpp b/include/CommonAPI/Event.hpp index ab656f8..d2be59d 100644 --- a/include/CommonAPI/Event.hpp +++ b/include/CommonAPI/Event.hpp @@ -97,8 +97,8 @@ private: ListenersMap pendingSubscriptions_; SubscriptionsSet pendingUnsubscriptions_; - std::mutex notificationMutex_; - std::mutex subscriptionMutex_; + std::recursive_mutex mutex_; + std::mutex abi_placeholder_; }; template<typename ... Arguments_> @@ -107,13 +107,14 @@ typename Event<Arguments_...>::Subscription Event<Arguments_...>::subscribe(List bool isFirstListener; Listeners listeners; - subscriptionMutex_.lock(); - subscription = nextSubscription_++; - isFirstListener = (0 == pendingSubscriptions_.size()) && (pendingUnsubscriptions_.size() == subscriptions_.size()); - listener = std::move(listener); - listeners = std::make_tuple(listener, std::move(errorListener)); - pendingSubscriptions_[subscription] = std::move(listeners); - subscriptionMutex_.unlock(); + { + std::lock_guard<std::recursive_mutex> itsLock(mutex_); + subscription = nextSubscription_++; + isFirstListener = (0 == pendingSubscriptions_.size()) && (pendingUnsubscriptions_.size() == subscriptions_.size()); + listener = std::move(listener); + listeners = std::make_tuple(listener, std::move(errorListener)); + pendingSubscriptions_[subscription] = std::move(listeners); + } if (isFirstListener) { if (!pendingUnsubscriptions_.empty()) @@ -131,30 +132,31 @@ void Event<Arguments_...>::unsubscribe(const Subscription subscription) { bool hasUnsubscribed(false); Listener listener; - subscriptionMutex_.lock(); - auto listenerIterator = subscriptions_.find(subscription); - if (subscriptions_.end() != listenerIterator) { - if (pendingUnsubscriptions_.end() == pendingUnsubscriptions_.find(subscription)) { - if (0 == pendingSubscriptions_.erase(subscription)) { - pendingUnsubscriptions_.insert(subscription); - listener = std::get<0>(listenerIterator->second); - hasUnsubscribed = true; + { + std::lock_guard<std::recursive_mutex> itsLock(mutex_); + auto listenerIterator = subscriptions_.find(subscription); + if (subscriptions_.end() != listenerIterator) { + if (pendingUnsubscriptions_.end() == pendingUnsubscriptions_.find(subscription)) { + if (0 == pendingSubscriptions_.erase(subscription)) { + pendingUnsubscriptions_.insert(subscription); + listener = std::get<0>(listenerIterator->second); + hasUnsubscribed = true; + } + isLastListener = (pendingUnsubscriptions_.size() == subscriptions_.size()); } - isLastListener = (pendingUnsubscriptions_.size() == subscriptions_.size()); } - } - else { - listenerIterator = pendingSubscriptions_.find(subscription); - if (pendingSubscriptions_.end() != listenerIterator) { - listener = std::get<0>(listenerIterator->second); - if (0 != pendingSubscriptions_.erase(subscription)) { - isLastListener = (pendingUnsubscriptions_.size() == subscriptions_.size()); - hasUnsubscribed = true; + else { + listenerIterator = pendingSubscriptions_.find(subscription); + if (pendingSubscriptions_.end() != listenerIterator) { + listener = std::get<0>(listenerIterator->second); + if (0 != pendingSubscriptions_.erase(subscription)) { + isLastListener = (pendingUnsubscriptions_.size() == subscriptions_.size()); + hasUnsubscribed = true; + } } } + isLastListener = isLastListener && (0 == pendingSubscriptions_.size()); } - isLastListener = isLastListener && (0 == pendingSubscriptions_.size()); - subscriptionMutex_.unlock(); if (hasUnsubscribed) { onListenerRemoved(listener, subscription); @@ -166,8 +168,7 @@ void Event<Arguments_...>::unsubscribe(const Subscription subscription) { template<typename ... Arguments_> void Event<Arguments_...>::notifyListeners(const Arguments_&... eventArguments) { - subscriptionMutex_.lock(); - notificationMutex_.lock(); + std::lock_guard<std::recursive_mutex> itsLock(mutex_); for (auto iterator = pendingUnsubscriptions_.begin(); iterator != pendingUnsubscriptions_.end(); iterator++) { @@ -182,18 +183,14 @@ void Event<Arguments_...>::notifyListeners(const Arguments_&... eventArguments) } pendingSubscriptions_.clear(); - subscriptionMutex_.unlock(); for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) { (std::get<0>(iterator->second))(eventArguments...); } - - notificationMutex_.unlock(); } template<typename ... Arguments_> void Event<Arguments_...>::notifySpecificListener(const Subscription subscription, const Arguments_&... eventArguments) { - subscriptionMutex_.lock(); - notificationMutex_.lock(); + std::lock_guard<std::recursive_mutex> itsLock(mutex_); for (auto iterator = pendingUnsubscriptions_.begin(); iterator != pendingUnsubscriptions_.end(); iterator++) { @@ -209,22 +206,16 @@ void Event<Arguments_...>::notifySpecificListener(const Subscription subscriptio } pendingSubscriptions_.clear(); - - subscriptionMutex_.unlock(); for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) { if (subscription == iterator->first) { (std::get<0>(iterator->second))(eventArguments...); } } - - notificationMutex_.unlock(); } template<typename ... Arguments_> void Event<Arguments_...>::notifySpecificError(const Subscription subscription, const CallStatus status) { - - subscriptionMutex_.lock(); - notificationMutex_.lock(); + std::lock_guard<std::recursive_mutex> itsLock(mutex_); for (auto iterator = pendingUnsubscriptions_.begin(); iterator != pendingUnsubscriptions_.end(); iterator++) { @@ -239,7 +230,6 @@ void Event<Arguments_...>::notifySpecificError(const Subscription subscription, } pendingSubscriptions_.clear(); - subscriptionMutex_.unlock(); for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) { if (subscription == iterator->first) { ErrorListener listener = std::get<1>(iterator->second); @@ -249,10 +239,7 @@ void Event<Arguments_...>::notifySpecificError(const Subscription subscription, } } - notificationMutex_.unlock(); - if (status != CommonAPI::CallStatus::SUCCESS) { - subscriptionMutex_.lock(); auto listenerIterator = subscriptions_.find(subscription); if (subscriptions_.end() != listenerIterator) { if (pendingUnsubscriptions_.end() == pendingUnsubscriptions_.find(subscription)) { @@ -267,14 +254,12 @@ void Event<Arguments_...>::notifySpecificError(const Subscription subscription, pendingSubscriptions_.erase(subscription); } } - subscriptionMutex_.unlock(); } } template<typename ... Arguments_> void Event<Arguments_...>::notifyErrorListeners(const CallStatus status) { - subscriptionMutex_.lock(); - notificationMutex_.lock(); + std::lock_guard<std::recursive_mutex> itsLock(mutex_); for (auto iterator = pendingUnsubscriptions_.begin(); iterator != pendingUnsubscriptions_.end(); iterator++) { @@ -289,16 +274,12 @@ void Event<Arguments_...>::notifyErrorListeners(const CallStatus status) { } pendingSubscriptions_.clear(); - subscriptionMutex_.unlock(); - for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) { ErrorListener listener = std::get<1>(iterator->second); if (listener) { listener(status); } } - - notificationMutex_.unlock(); } diff --git a/include/CommonAPI/Variant.hpp b/include/CommonAPI/Variant.hpp index db1cf7b..c6cd40f 100644 --- a/include/CommonAPI/Variant.hpp +++ b/include/CommonAPI/Variant.hpp @@ -619,7 +619,9 @@ Variant<Types_...>::Variant() } template<typename... Types_> -Variant<Types_...>::Variant(const Variant &_source) { +Variant<Types_...>::Variant(const Variant &_source) : + valueType_(_source.valueType_) +{ AssignmentVisitor<Types_...> visitor(*this, false); ApplyVoidVisitor< AssignmentVisitor<Types_...> , Variant<Types_...>, Types_... @@ -627,7 +629,8 @@ Variant<Types_...>::Variant(const Variant &_source) { } template<typename... Types_> -Variant<Types_...>::Variant(Variant &&_source) +Variant<Types_...>::Variant(Variant &&_source) : + valueType_(_source.valueType_) { AssignmentVisitor<Types_...> visitor(*this, false); ApplyVoidVisitor< @@ -688,7 +691,9 @@ template<typename Type_> Variant<Types_...>::Variant(const Type_ &_value, typename std::enable_if<!std::is_const<Type_>::value>::type*, typename std::enable_if<!std::is_reference<Type_>::value>::type*, - typename std::enable_if<!std::is_same<Type_, Variant<Types_...>>::value>::type*) { + typename std::enable_if<!std::is_same<Type_, Variant<Types_...>>::value>::type*) : + valueType_(0x0) +{ set<typename TypeSelector<Type_, Types_...>::type>(_value, false); } @@ -697,7 +702,9 @@ template<typename Type_> Variant<Types_...>::Variant(Type_ &&_value, typename std::enable_if<!std::is_const<Type_>::value>::type*, typename std::enable_if<!std::is_reference<Type_>::value>::type*, -typename std::enable_if<!std::is_same<Type_, Variant<Types_...>>::value>::type*) { +typename std::enable_if<!std::is_same<Type_, Variant<Types_...>>::value>::type*) : + valueType_(0x0) +{ set<typename TypeSelector<Type_, Types_...>::type>(std::move(_value), false); } |