@@ -710,19 +710,17 @@ class queue_impl {
710710 void *getTraceEvent () { return MTraceEvent; }
711711
712712 void setExternalEvent (const event &Event) {
713- std::lock_guard<std::mutex> Lock (MInOrderExternalEventMtx);
714- MHasValueInOrderExternalEvent. store ( true , std::memory_order_release) ;
715- MInOrderExternalEvent = Event ;
713+ MInOrderExternalEvent. put ([&Event]( std::optional<event> &InOrderExternalEvent){
714+ InOrderExternalEvent = Event ;
715+ }) ;
716716 }
717717
718718 std::optional<event> popExternalEvent () {
719719 std::optional<event> Result = std::nullopt ;
720720
721- if (MHasValueInOrderExternalEvent.load (std::memory_order_acquire)) {
722- std::lock_guard<std::mutex> Lock (MInOrderExternalEventMtx);
723- MHasValueInOrderExternalEvent.store (false , std::memory_order_release);
724- std::swap (Result, MInOrderExternalEvent);
725- }
721+ MInOrderExternalEvent.get ([&Result](std::optional<event> &InOrderExternalEvent) {
722+ std::swap (Result, InOrderExternalEvent);
723+ });
726724 return Result;
727725 }
728726
@@ -838,14 +836,11 @@ class queue_impl {
838836 // dependency so in the case where some commands were not enqueued
839837 // (blocked), we track them to prevent barrier from being enqueued
840838 // earlier.
841- if (MAreCleanupRequestsMissed.load (std::memory_order_acquire))
842- {
843- std::lock_guard<std::mutex> RequestLock (MMissedCleanupRequestsMtx);
844- MAreCleanupRequestsMissed.store (false , std::memory_order_release);
845- for (auto &UpdatedGraph : MMissedCleanupRequests)
839+ MMissedCleanupRequests.get ([this ](MissedCleanupRequestsType &MissedCleanupRequests){
840+ for (auto &UpdatedGraph : MissedCleanupRequests)
846841 doUnenqueuedCommandCleanup (UpdatedGraph);
847- MMissedCleanupRequests .clear ();
848- }
842+ MissedCleanupRequests .clear ();
843+ });
849844 auto &Deps = MGraph.expired () ? MDefaultGraphDeps : MExtGraphDeps;
850845 if (Type == CGType::Barrier && !Deps.UnenqueuedCmdEvents .empty ()) {
851846 Handler.depends_on (Deps.UnenqueuedCmdEvents );
@@ -1029,6 +1024,38 @@ class queue_impl {
10291024 }
10301025 } MDefaultGraphDeps, MExtGraphDeps;
10311026
1027+ // implement check-lock-check pattern to not lock empty MData
1028+ template <typename DataType>
1029+ class CheckLockCheck {
1030+ DataType MData;
1031+ std::atomic_bool MDataPresent = false ;
1032+ mutable std::mutex MDataMtx;
1033+ public:
1034+ template <typename F>
1035+ void put (F &&func) {
1036+ std::lock_guard<std::mutex> Lock (MDataMtx);
1037+ MDataPresent.store (true , std::memory_order_release);
1038+ func (MData);
1039+ }
1040+ template <typename F>
1041+ void get (F &&func) {
1042+ if (MDataPresent.load (std::memory_order_acquire)) {
1043+ std::lock_guard<std::mutex> Lock (MDataMtx);
1044+ if (MDataPresent.load (std::memory_order_acquire)) {
1045+ func (MData);
1046+ MDataPresent.store (false , std::memory_order_release);
1047+ }
1048+ }
1049+ }
1050+ template <typename F>
1051+ DataType read (F &&func) {
1052+ if (!MDataPresent.load (std::memory_order_acquire))
1053+ return DataType{};
1054+ std::lock_guard<std::mutex> Lock (MDataMtx);
1055+ return func (MData);
1056+ }
1057+ };
1058+
10321059 const bool MIsInorder;
10331060
10341061 std::vector<EventImplPtr> MStreamsServiceEvents;
@@ -1047,14 +1074,11 @@ class queue_impl {
10471074 // the fallback implementation of profiling info
10481075 bool MFallbackProfiling = false ;
10491076
1050- // Is value presented in MInOrderExternalEvent?
1051- std::atomic_bool MHasValueInOrderExternalEvent = false ;
10521077 // This event can be optionally provided by users for in-order queues to add
10531078 // an additional dependency for the subsequent submission in to the queue.
10541079 // Access to the event should be guarded with MInOrderExternalEventMtx.
10551080 // NOTE: std::optional must not be exposed in the ABI.
1056- std::optional<event> MInOrderExternalEvent;
1057- mutable std::mutex MInOrderExternalEventMtx;
1081+ CheckLockCheck<std::optional<event>> MInOrderExternalEvent;
10581082
10591083public:
10601084 // Queue constructed with the discard_events property
@@ -1077,10 +1101,9 @@ class queue_impl {
10771101 unsigned long long MQueueID;
10781102 static std::atomic<unsigned long long > MNextAvailableQueueID;
10791103
1080- std::deque<std::shared_ptr<ext::oneapi::experimental::detail::graph_impl>>
1081- MMissedCleanupRequests;
1082- std::mutex MMissedCleanupRequestsMtx;
1083- std::atomic_bool MAreCleanupRequestsMissed = false ;
1104+ using MissedCleanupRequestsType =
1105+ std::deque<std::shared_ptr<ext::oneapi::experimental::detail::graph_impl>>;
1106+ CheckLockCheck<MissedCleanupRequestsType> MMissedCleanupRequests;
10841107
10851108 friend class sycl ::ext::oneapi::experimental::detail::node_impl;
10861109
0 commit comments