summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLutz Bichler <Lutz.Bichler@bmw.de>2019-07-22 12:12:02 +0200
committerLutz Bichler <Lutz.Bichler@bmw.de>2019-07-22 12:12:02 +0200
commit99ebf3461f51e4899f06457d6aafdaa4adecd278 (patch)
treee41d0fbc8682601c80ce9a892f77a8fa355721db
parent2fd0625d21f1fa8e6a3adfc89ce9f381a4d33990 (diff)
downloadgenivi-common-api-runtime-99ebf3461f51e4899f06457d6aafdaa4adecd278.tar.gz
capicxx-core-runtime 3.1.12.63.1.12.6
-rw-r--r--CHANGES6
-rw-r--r--include/CommonAPI/Event.hpp87
-rw-r--r--include/CommonAPI/Variant.hpp15
3 files changed, 51 insertions, 57 deletions
diff --git a/CHANGES b/CHANGES
index f115e84..65ddba3 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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);
}