@@ -710,14 +710,18 @@ class queue_impl {
710
710
void *getTraceEvent () { return MTraceEvent; }
711
711
712
712
void setExternalEvent (const event &Event) {
713
- std::lock_guard<std::mutex> Lock (MInOrderExternalEventMtx);
714
- MInOrderExternalEvent = Event;
713
+ MInOrderExternalEvent.set ([&](std::optional<event> &InOrderExternalEvent) {
714
+ InOrderExternalEvent = Event;
715
+ });
715
716
}
716
717
717
718
std::optional<event> popExternalEvent () {
718
- std::lock_guard<std::mutex> Lock (MInOrderExternalEventMtx);
719
719
std::optional<event> Result = std::nullopt;
720
- std::swap (Result, MInOrderExternalEvent);
720
+
721
+ MInOrderExternalEvent.unset (
722
+ [&](std::optional<event> &InOrderExternalEvent) {
723
+ std::swap (Result, InOrderExternalEvent);
724
+ });
721
725
return Result;
722
726
}
723
727
@@ -1025,6 +1029,36 @@ class queue_impl {
1025
1029
}
1026
1030
} MDefaultGraphDeps, MExtGraphDeps;
1027
1031
1032
+ // Implement check-lock-check pattern to not lock empty MData as the locks
1033
+ // come with runtime overhead.
1034
+ template <typename DataType> class CheckLockCheck {
1035
+ DataType MData;
1036
+ std::atomic_bool MIsSet = false ;
1037
+ mutable std::mutex MDataMtx;
1038
+
1039
+ public:
1040
+ template <typename F> void set (F &&func) {
1041
+ std::lock_guard<std::mutex> Lock (MDataMtx);
1042
+ MIsSet.store (true , std::memory_order_release);
1043
+ std::forward<F>(func)(MData);
1044
+ }
1045
+ template <typename F> void unset (F &&func) {
1046
+ if (MIsSet.load (std::memory_order_acquire)) {
1047
+ std::lock_guard<std::mutex> Lock (MDataMtx);
1048
+ if (MIsSet.load (std::memory_order_acquire)) {
1049
+ std::forward<F>(func)(MData);
1050
+ MIsSet.store (false , std::memory_order_release);
1051
+ }
1052
+ }
1053
+ }
1054
+ DataType read () {
1055
+ if (!MIsSet.load (std::memory_order_acquire))
1056
+ return DataType{};
1057
+ std::lock_guard<std::mutex> Lock (MDataMtx);
1058
+ return MData;
1059
+ }
1060
+ };
1061
+
1028
1062
const bool MIsInorder;
1029
1063
1030
1064
std::vector<EventImplPtr> MStreamsServiceEvents;
@@ -1045,10 +1079,9 @@ class queue_impl {
1045
1079
1046
1080
// This event can be optionally provided by users for in-order queues to add
1047
1081
// an additional dependency for the subsequent submission in to the queue.
1048
- // Access to the event should be guarded with MInOrderExternalEventMtx .
1082
+ // Access to the event should be guarded with mutex .
1049
1083
// NOTE: std::optional must not be exposed in the ABI.
1050
- std::optional<event> MInOrderExternalEvent;
1051
- mutable std::mutex MInOrderExternalEventMtx;
1084
+ CheckLockCheck<std::optional<event>> MInOrderExternalEvent;
1052
1085
1053
1086
public:
1054
1087
// Queue constructed with the discard_events property
0 commit comments