Skip to content

Commit 99ebf34

Browse files
committed
capicxx-core-runtime 3.1.12.6
1 parent 2fd0625 commit 99ebf34

File tree

3 files changed

+51
-57
lines changed

3 files changed

+51
-57
lines changed

CHANGES

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
Changes
22
=======
33

4+
v3.1.12.6
5+
- Fix race condition leading to event delivery after unsubscription
6+
7+
v3.1.12.5
8+
- Initialize valueType in copy ctors of Variant class
9+
410
v3.1.12.4
511
- Fix calling of registered subscription status handlers for
612
selective broadcasts

include/CommonAPI/Event.hpp

Lines changed: 34 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ class Event {
9797
ListenersMap pendingSubscriptions_;
9898
SubscriptionsSet pendingUnsubscriptions_;
9999

100-
std::mutex notificationMutex_;
101-
std::mutex subscriptionMutex_;
100+
std::recursive_mutex mutex_;
101+
std::mutex abi_placeholder_;
102102
};
103103

104104
template<typename ... Arguments_>
@@ -107,13 +107,14 @@ typename Event<Arguments_...>::Subscription Event<Arguments_...>::subscribe(List
107107
bool isFirstListener;
108108
Listeners listeners;
109109

110-
subscriptionMutex_.lock();
111-
subscription = nextSubscription_++;
112-
isFirstListener = (0 == pendingSubscriptions_.size()) && (pendingUnsubscriptions_.size() == subscriptions_.size());
113-
listener = std::move(listener);
114-
listeners = std::make_tuple(listener, std::move(errorListener));
115-
pendingSubscriptions_[subscription] = std::move(listeners);
116-
subscriptionMutex_.unlock();
110+
{
111+
std::lock_guard<std::recursive_mutex> itsLock(mutex_);
112+
subscription = nextSubscription_++;
113+
isFirstListener = (0 == pendingSubscriptions_.size()) && (pendingUnsubscriptions_.size() == subscriptions_.size());
114+
listener = std::move(listener);
115+
listeners = std::make_tuple(listener, std::move(errorListener));
116+
pendingSubscriptions_[subscription] = std::move(listeners);
117+
}
117118

118119
if (isFirstListener) {
119120
if (!pendingUnsubscriptions_.empty())
@@ -131,30 +132,31 @@ void Event<Arguments_...>::unsubscribe(const Subscription subscription) {
131132
bool hasUnsubscribed(false);
132133
Listener listener;
133134

134-
subscriptionMutex_.lock();
135-
auto listenerIterator = subscriptions_.find(subscription);
136-
if (subscriptions_.end() != listenerIterator) {
137-
if (pendingUnsubscriptions_.end() == pendingUnsubscriptions_.find(subscription)) {
138-
if (0 == pendingSubscriptions_.erase(subscription)) {
139-
pendingUnsubscriptions_.insert(subscription);
140-
listener = std::get<0>(listenerIterator->second);
141-
hasUnsubscribed = true;
135+
{
136+
std::lock_guard<std::recursive_mutex> itsLock(mutex_);
137+
auto listenerIterator = subscriptions_.find(subscription);
138+
if (subscriptions_.end() != listenerIterator) {
139+
if (pendingUnsubscriptions_.end() == pendingUnsubscriptions_.find(subscription)) {
140+
if (0 == pendingSubscriptions_.erase(subscription)) {
141+
pendingUnsubscriptions_.insert(subscription);
142+
listener = std::get<0>(listenerIterator->second);
143+
hasUnsubscribed = true;
144+
}
145+
isLastListener = (pendingUnsubscriptions_.size() == subscriptions_.size());
142146
}
143-
isLastListener = (pendingUnsubscriptions_.size() == subscriptions_.size());
144147
}
145-
}
146-
else {
147-
listenerIterator = pendingSubscriptions_.find(subscription);
148-
if (pendingSubscriptions_.end() != listenerIterator) {
149-
listener = std::get<0>(listenerIterator->second);
150-
if (0 != pendingSubscriptions_.erase(subscription)) {
151-
isLastListener = (pendingUnsubscriptions_.size() == subscriptions_.size());
152-
hasUnsubscribed = true;
148+
else {
149+
listenerIterator = pendingSubscriptions_.find(subscription);
150+
if (pendingSubscriptions_.end() != listenerIterator) {
151+
listener = std::get<0>(listenerIterator->second);
152+
if (0 != pendingSubscriptions_.erase(subscription)) {
153+
isLastListener = (pendingUnsubscriptions_.size() == subscriptions_.size());
154+
hasUnsubscribed = true;
155+
}
153156
}
154157
}
158+
isLastListener = isLastListener && (0 == pendingSubscriptions_.size());
155159
}
156-
isLastListener = isLastListener && (0 == pendingSubscriptions_.size());
157-
subscriptionMutex_.unlock();
158160

159161
if (hasUnsubscribed) {
160162
onListenerRemoved(listener, subscription);
@@ -166,8 +168,7 @@ void Event<Arguments_...>::unsubscribe(const Subscription subscription) {
166168

167169
template<typename ... Arguments_>
168170
void Event<Arguments_...>::notifyListeners(const Arguments_&... eventArguments) {
169-
subscriptionMutex_.lock();
170-
notificationMutex_.lock();
171+
std::lock_guard<std::recursive_mutex> itsLock(mutex_);
171172
for (auto iterator = pendingUnsubscriptions_.begin();
172173
iterator != pendingUnsubscriptions_.end();
173174
iterator++) {
@@ -182,18 +183,14 @@ void Event<Arguments_...>::notifyListeners(const Arguments_&... eventArguments)
182183
}
183184
pendingSubscriptions_.clear();
184185

185-
subscriptionMutex_.unlock();
186186
for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) {
187187
(std::get<0>(iterator->second))(eventArguments...);
188188
}
189-
190-
notificationMutex_.unlock();
191189
}
192190

193191
template<typename ... Arguments_>
194192
void Event<Arguments_...>::notifySpecificListener(const Subscription subscription, const Arguments_&... eventArguments) {
195-
subscriptionMutex_.lock();
196-
notificationMutex_.lock();
193+
std::lock_guard<std::recursive_mutex> itsLock(mutex_);
197194
for (auto iterator = pendingUnsubscriptions_.begin();
198195
iterator != pendingUnsubscriptions_.end();
199196
iterator++) {
@@ -209,22 +206,16 @@ void Event<Arguments_...>::notifySpecificListener(const Subscription subscriptio
209206
}
210207
pendingSubscriptions_.clear();
211208

212-
213-
subscriptionMutex_.unlock();
214209
for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) {
215210
if (subscription == iterator->first) {
216211
(std::get<0>(iterator->second))(eventArguments...);
217212
}
218213
}
219-
220-
notificationMutex_.unlock();
221214
}
222215

223216
template<typename ... Arguments_>
224217
void Event<Arguments_...>::notifySpecificError(const Subscription subscription, const CallStatus status) {
225-
226-
subscriptionMutex_.lock();
227-
notificationMutex_.lock();
218+
std::lock_guard<std::recursive_mutex> itsLock(mutex_);
228219
for (auto iterator = pendingUnsubscriptions_.begin();
229220
iterator != pendingUnsubscriptions_.end();
230221
iterator++) {
@@ -239,7 +230,6 @@ void Event<Arguments_...>::notifySpecificError(const Subscription subscription,
239230
}
240231
pendingSubscriptions_.clear();
241232

242-
subscriptionMutex_.unlock();
243233
for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) {
244234
if (subscription == iterator->first) {
245235
ErrorListener listener = std::get<1>(iterator->second);
@@ -249,10 +239,7 @@ void Event<Arguments_...>::notifySpecificError(const Subscription subscription,
249239
}
250240
}
251241

252-
notificationMutex_.unlock();
253-
254242
if (status != CommonAPI::CallStatus::SUCCESS) {
255-
subscriptionMutex_.lock();
256243
auto listenerIterator = subscriptions_.find(subscription);
257244
if (subscriptions_.end() != listenerIterator) {
258245
if (pendingUnsubscriptions_.end() == pendingUnsubscriptions_.find(subscription)) {
@@ -267,14 +254,12 @@ void Event<Arguments_...>::notifySpecificError(const Subscription subscription,
267254
pendingSubscriptions_.erase(subscription);
268255
}
269256
}
270-
subscriptionMutex_.unlock();
271257
}
272258
}
273259

274260
template<typename ... Arguments_>
275261
void Event<Arguments_...>::notifyErrorListeners(const CallStatus status) {
276-
subscriptionMutex_.lock();
277-
notificationMutex_.lock();
262+
std::lock_guard<std::recursive_mutex> itsLock(mutex_);
278263
for (auto iterator = pendingUnsubscriptions_.begin();
279264
iterator != pendingUnsubscriptions_.end();
280265
iterator++) {
@@ -289,16 +274,12 @@ void Event<Arguments_...>::notifyErrorListeners(const CallStatus status) {
289274
}
290275
pendingSubscriptions_.clear();
291276

292-
subscriptionMutex_.unlock();
293-
294277
for (auto iterator = subscriptions_.begin(); iterator != subscriptions_.end(); iterator++) {
295278
ErrorListener listener = std::get<1>(iterator->second);
296279
if (listener) {
297280
listener(status);
298281
}
299282
}
300-
301-
notificationMutex_.unlock();
302283
}
303284

304285

include/CommonAPI/Variant.hpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -619,15 +619,18 @@ Variant<Types_...>::Variant()
619619
}
620620

621621
template<typename... Types_>
622-
Variant<Types_...>::Variant(const Variant &_source) {
622+
Variant<Types_...>::Variant(const Variant &_source) :
623+
valueType_(_source.valueType_)
624+
{
623625
AssignmentVisitor<Types_...> visitor(*this, false);
624626
ApplyVoidVisitor<
625627
AssignmentVisitor<Types_...> , Variant<Types_...>, Types_...
626628
>::visit(visitor, _source);
627629
}
628630

629631
template<typename... Types_>
630-
Variant<Types_...>::Variant(Variant &&_source)
632+
Variant<Types_...>::Variant(Variant &&_source) :
633+
valueType_(_source.valueType_)
631634
{
632635
AssignmentVisitor<Types_...> visitor(*this, false);
633636
ApplyVoidVisitor<
@@ -688,7 +691,9 @@ template<typename Type_>
688691
Variant<Types_...>::Variant(const Type_ &_value,
689692
typename std::enable_if<!std::is_const<Type_>::value>::type*,
690693
typename std::enable_if<!std::is_reference<Type_>::value>::type*,
691-
typename std::enable_if<!std::is_same<Type_, Variant<Types_...>>::value>::type*) {
694+
typename std::enable_if<!std::is_same<Type_, Variant<Types_...>>::value>::type*) :
695+
valueType_(0x0)
696+
{
692697
set<typename TypeSelector<Type_, Types_...>::type>(_value, false);
693698
}
694699

@@ -697,7 +702,9 @@ template<typename Type_>
697702
Variant<Types_...>::Variant(Type_ &&_value,
698703
typename std::enable_if<!std::is_const<Type_>::value>::type*,
699704
typename std::enable_if<!std::is_reference<Type_>::value>::type*,
700-
typename std::enable_if<!std::is_same<Type_, Variant<Types_...>>::value>::type*) {
705+
typename std::enable_if<!std::is_same<Type_, Variant<Types_...>>::value>::type*) :
706+
valueType_(0x0)
707+
{
701708
set<typename TypeSelector<Type_, Types_...>::type>(std::move(_value), false);
702709
}
703710

0 commit comments

Comments
 (0)