33
44#include < algorithm>
55#include < cstddef>
6+ #include < mutex>
67#include < vector>
78
89namespace
@@ -21,10 +22,12 @@ inline bool is_event_complete(const sycl::event &e)
2122class SequentialOrder
2223{
2324private:
25+ mutable std::mutex mu_events;
2426 std::vector<sycl::event> host_task_events;
2527 std::vector<sycl::event> submitted_events;
2628
27- void prune_complete ()
29+ // only called with mu_events held
30+ void prune_complete_nolock ()
2831 {
2932 const auto &ht_it =
3033 std::remove_if (host_task_events.begin (), host_task_events.end (),
@@ -46,76 +49,78 @@ class SequentialOrder
4649 }
4750
4851 SequentialOrder (const SequentialOrder &other)
49- : host_task_events(other.host_task_events),
50- submitted_events (other.submitted_events)
5152 {
52- prune_complete ();
53+ std::lock_guard<std::mutex> lock (other.mu_events );
54+ host_task_events = other.host_task_events ;
55+ submitted_events = other.submitted_events ;
56+ prune_complete_nolock ();
5357 }
5458 SequentialOrder (SequentialOrder &&other)
5559 : host_task_events{}, submitted_events{}
5660 {
61+ std::lock_guard<std::mutex> lock (other.mu_events );
5762 host_task_events = std::move (other.host_task_events );
5863 submitted_events = std::move (other.submitted_events );
59- prune_complete ();
64+ prune_complete_nolock ();
6065 }
6166
6267 SequentialOrder &operator =(const SequentialOrder &other)
6368 {
64- host_task_events = other.host_task_events ;
65- submitted_events = other.submitted_events ;
66-
67- prune_complete ();
69+ if (this != &other) {
70+ std::scoped_lock lock (mu_events, other.mu_events );
71+ host_task_events = other.host_task_events ;
72+ submitted_events = other.submitted_events ;
73+ prune_complete_nolock ();
74+ }
6875 return *this ;
6976 }
7077
7178 SequentialOrder &operator =(SequentialOrder &&other)
7279 {
7380 if (this != &other) {
81+ std::scoped_lock lock (mu_events, other.mu_events );
7482 host_task_events = std::move (other.host_task_events );
7583 submitted_events = std::move (other.submitted_events );
76- prune_complete ();
84+ prune_complete_nolock ();
7785 }
7886 return *this ;
7987 }
8088
8189 std::size_t get_num_submitted_events () const
8290 {
91+ std::lock_guard<std::mutex> lock (mu_events);
8392 return submitted_events.size ();
8493 }
8594
86- const std::vector<sycl::event> &get_host_task_events ()
95+ // returns a copy to avoid returning a reference that
96+ // could be modified after the lock is released
97+ std::vector<sycl::event> get_host_task_events ()
8798 {
88- prune_complete ();
99+ std::lock_guard<std::mutex> lock (mu_events);
100+ prune_complete_nolock ();
89101 return host_task_events;
90102 }
91103
92- /*
93- const std::vector<sycl::event> & get_host_task_events() const {
94- return host_task_events;
95- }
96- */
97-
98104 std::size_t get_num_host_task_events () const
99105 {
106+ std::lock_guard<std::mutex> lock (mu_events);
100107 return host_task_events.size ();
101108 }
102109
103- const std::vector<sycl::event> &get_submitted_events ()
110+ // returns a copy to avoid returning a reference that
111+ // could be modified after the lock is released
112+ std::vector<sycl::event> get_submitted_events ()
104113 {
105- prune_complete ();
114+ std::lock_guard<std::mutex> lock (mu_events);
115+ prune_complete_nolock ();
106116 return submitted_events;
107117 }
108118
109- /*
110- const std::vector<sycl::event> & get_submitted_events() const {
111- return submitted_events;
112- }
113- */
114-
115119 void add_to_both_events (const sycl::event &ht_ev,
116120 const sycl::event &comp_ev)
117121 {
118- prune_complete ();
122+ std::lock_guard<std::mutex> lock (mu_events);
123+ prune_complete_nolock ();
119124 if (!is_event_complete (ht_ev))
120125 host_task_events.push_back (ht_ev);
121126 if (!is_event_complete (comp_ev))
@@ -125,7 +130,8 @@ class SequentialOrder
125130 void add_vector_to_both_events (const std::vector<sycl::event> &ht_evs,
126131 const std::vector<sycl::event> &comp_evs)
127132 {
128- prune_complete ();
133+ std::lock_guard<std::mutex> lock (mu_events);
134+ prune_complete_nolock ();
129135 for (const auto &e : ht_evs) {
130136 if (!is_event_complete (e))
131137 host_task_events.push_back (e);
@@ -138,15 +144,17 @@ class SequentialOrder
138144
139145 void add_to_host_task_events (const sycl::event &ht_ev)
140146 {
141- prune_complete ();
147+ std::lock_guard<std::mutex> lock (mu_events);
148+ prune_complete_nolock ();
142149 if (!is_event_complete (ht_ev)) {
143150 host_task_events.push_back (ht_ev);
144151 }
145152 }
146153
147154 void add_to_submitted_events (const sycl::event &comp_ev)
148155 {
149- prune_complete ();
156+ std::lock_guard<std::mutex> lock (mu_events);
157+ prune_complete_nolock ();
150158 if (!is_event_complete (comp_ev)) {
151159 submitted_events.push_back (comp_ev);
152160 }
@@ -155,7 +163,8 @@ class SequentialOrder
155163 template <std::size_t num>
156164 void add_list_to_host_task_events (const sycl::event (&ht_events)[num])
157165 {
158- prune_complete ();
166+ std::lock_guard<std::mutex> lock (mu_events);
167+ prune_complete_nolock ();
159168 for (std::size_t i = 0 ; i < num; ++i) {
160169 const auto &e = ht_events[i];
161170 if (!is_event_complete (e))
@@ -166,7 +175,8 @@ class SequentialOrder
166175 template <std::size_t num>
167176 void add_list_to_submitted_events (const sycl::event (&comp_events)[num])
168177 {
169- prune_complete ();
178+ std::lock_guard<std::mutex> lock (mu_events);
179+ prune_complete_nolock ();
170180 for (std::size_t i = 0 ; i < num; ++i) {
171181 const auto &e = comp_events[i];
172182 if (!is_event_complete (e))
@@ -176,8 +186,20 @@ class SequentialOrder
176186
177187 void wait ()
178188 {
179- sycl::event::wait (submitted_events);
180- sycl::event::wait (host_task_events);
181- prune_complete ();
189+ // snapeshot events outside of mutex to avoid
190+ // calling wait inside mutex
191+ std::vector<sycl::event> sub_copy;
192+ std::vector<sycl::event> ht_copy;
193+ {
194+ std::lock_guard<std::mutex> lock (mu_events);
195+ sub_copy = submitted_events;
196+ ht_copy = host_task_events;
197+ }
198+ sycl::event::wait (sub_copy);
199+ sycl::event::wait (ht_copy);
200+ {
201+ std::lock_guard<std::mutex> lock (mu_events);
202+ prune_complete_nolock ();
203+ }
182204 }
183205};
0 commit comments