]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/compute/include/boost/compute/event.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / compute / include / boost / compute / event.hpp
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 // See http://boostorg.github.com/compute for more information.
9 //---------------------------------------------------------------------------//
10
11 #ifndef BOOST_COMPUTE_EVENT_HPP
12 #define BOOST_COMPUTE_EVENT_HPP
13
14 #include <boost/function.hpp>
15
16 #include <boost/compute/config.hpp>
17 #include <boost/compute/exception.hpp>
18 #include <boost/compute/detail/duration.hpp>
19 #include <boost/compute/detail/get_object_info.hpp>
20 #include <boost/compute/detail/assert_cl_success.hpp>
21 #include <boost/compute/types/fundamental.hpp>
22
23 namespace boost {
24 namespace compute {
25
26 /// \class event
27 /// \brief An event corresponding to an operation on a compute device
28 ///
29 /// Event objects are used to track operations running on the device (such as
30 /// kernel executions and memory transfers). Event objects are returned by the
31 /// various \c enqueue_* methods of the command_queue class.
32 ///
33 /// Events can be used to synchronize operations between the host and the
34 /// device. The \c wait() method will block execution on the host until the
35 /// operation corresponding to the event on the device has completed. The
36 /// status of the operation can also be polled with the \c status() method.
37 ///
38 /// Event objects can also be used for performance profiling. In order to use
39 /// events for profiling, the command queue must be constructed with the
40 /// \c CL_QUEUE_PROFILING_ENABLE flag. Then the \c duration() method can be
41 /// used to retrieve the total duration of the operation on the device:
42 /// \code
43 /// std::cout << "time = " << e.duration<std::chrono::milliseconds>().count() << "ms\n";
44 /// \endcode
45 ///
46 /// \see \ref future "future<T>", wait_list
47 class event
48 {
49 public:
50 /// \internal_
51 enum execution_status {
52 complete = CL_COMPLETE,
53 running = CL_RUNNING,
54 submitted = CL_SUBMITTED,
55 queued = CL_QUEUED
56 };
57
58 /// \internal_
59 enum command_type {
60 ndrange_kernel = CL_COMMAND_NDRANGE_KERNEL,
61 task = CL_COMMAND_TASK,
62 native_kernel = CL_COMMAND_NATIVE_KERNEL,
63 read_buffer = CL_COMMAND_READ_BUFFER,
64 write_buffer = CL_COMMAND_WRITE_BUFFER,
65 copy_buffer = CL_COMMAND_COPY_BUFFER,
66 read_image = CL_COMMAND_READ_IMAGE,
67 write_image = CL_COMMAND_WRITE_IMAGE,
68 copy_image = CL_COMMAND_COPY_IMAGE,
69 copy_image_to_buffer = CL_COMMAND_COPY_IMAGE_TO_BUFFER,
70 copy_buffer_to_image = CL_COMMAND_COPY_BUFFER_TO_IMAGE,
71 map_buffer = CL_COMMAND_MAP_BUFFER,
72 map_image = CL_COMMAND_MAP_IMAGE,
73 unmap_mem_object = CL_COMMAND_UNMAP_MEM_OBJECT,
74 marker = CL_COMMAND_MARKER,
75 aquire_gl_objects = CL_COMMAND_ACQUIRE_GL_OBJECTS,
76 release_gl_object = CL_COMMAND_RELEASE_GL_OBJECTS
77 #if defined(CL_VERSION_1_1)
78 ,
79 read_buffer_rect = CL_COMMAND_READ_BUFFER_RECT,
80 write_buffer_rect = CL_COMMAND_WRITE_BUFFER_RECT,
81 copy_buffer_rect = CL_COMMAND_COPY_BUFFER_RECT
82 #endif
83 };
84
85 /// \internal_
86 enum profiling_info {
87 profiling_command_queued = CL_PROFILING_COMMAND_QUEUED,
88 profiling_command_submit = CL_PROFILING_COMMAND_SUBMIT,
89 profiling_command_start = CL_PROFILING_COMMAND_START,
90 profiling_command_end = CL_PROFILING_COMMAND_END
91 };
92
93 /// Creates a null event object.
94 event()
95 : m_event(0)
96 {
97 }
98
99 explicit event(cl_event event, bool retain = true)
100 : m_event(event)
101 {
102 if(m_event && retain){
103 clRetainEvent(event);
104 }
105 }
106
107 /// Makes a new event as a copy of \p other.
108 event(const event &other)
109 : m_event(other.m_event)
110 {
111 if(m_event){
112 clRetainEvent(m_event);
113 }
114 }
115
116 /// Copies the event object from \p other to \c *this.
117 event& operator=(const event &other)
118 {
119 if(this != &other){
120 if(m_event){
121 clReleaseEvent(m_event);
122 }
123
124 m_event = other.m_event;
125
126 if(m_event){
127 clRetainEvent(m_event);
128 }
129 }
130
131 return *this;
132 }
133
134 #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
135 /// Move-constructs a new event object from \p other.
136 event(event&& other) BOOST_NOEXCEPT
137 : m_event(other.m_event)
138 {
139 other.m_event = 0;
140 }
141
142 /// Move-assigns the event from \p other to \c *this.
143 event& operator=(event&& other) BOOST_NOEXCEPT
144 {
145 if(m_event){
146 clReleaseEvent(m_event);
147 }
148
149 m_event = other.m_event;
150 other.m_event = 0;
151
152 return *this;
153 }
154 #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
155
156 /// Destroys the event object.
157 ~event()
158 {
159 if(m_event){
160 BOOST_COMPUTE_ASSERT_CL_SUCCESS(
161 clReleaseEvent(m_event)
162 );
163 }
164 }
165
166 /// Returns a reference to the underlying OpenCL event object.
167 cl_event& get() const
168 {
169 return const_cast<cl_event &>(m_event);
170 }
171
172 /// Returns the status of the event.
173 cl_int status() const
174 {
175 return get_info<cl_int>(CL_EVENT_COMMAND_EXECUTION_STATUS);
176 }
177
178 /// Returns the command type for the event.
179 cl_command_type get_command_type() const
180 {
181 return get_info<cl_command_type>(CL_EVENT_COMMAND_TYPE);
182 }
183
184 /// Returns information about the event.
185 ///
186 /// \see_opencl_ref{clGetEventInfo}
187 template<class T>
188 T get_info(cl_event_info info) const
189 {
190 return detail::get_object_info<T>(clGetEventInfo, m_event, info);
191 }
192
193 /// \overload
194 template<int Enum>
195 typename detail::get_object_info_type<event, Enum>::type
196 get_info() const;
197
198 /// Returns profiling information for the event.
199 ///
200 /// \see event::duration()
201 ///
202 /// \see_opencl_ref{clGetEventProfilingInfo}
203 template<class T>
204 T get_profiling_info(cl_profiling_info info) const
205 {
206 return detail::get_object_info<T>(clGetEventProfilingInfo,
207 m_event,
208 info);
209 }
210
211 /// Blocks until the actions corresponding to the event have
212 /// completed.
213 void wait() const
214 {
215 cl_int ret = clWaitForEvents(1, &m_event);
216 if(ret != CL_SUCCESS){
217 BOOST_THROW_EXCEPTION(opencl_error(ret));
218 }
219 }
220
221 #if defined(CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
222 /// Registers a function to be called when the event status changes to
223 /// \p status (by default CL_COMPLETE). The callback is passed the OpenCL
224 /// event object, the event status, and a pointer to arbitrary user data.
225 ///
226 /// \see_opencl_ref{clSetEventCallback}
227 ///
228 /// \opencl_version_warning{1,1}
229 void set_callback(void (BOOST_COMPUTE_CL_CALLBACK *callback)(
230 cl_event event, cl_int status, void *user_data
231 ),
232 cl_int status = CL_COMPLETE,
233 void *user_data = 0)
234 {
235 cl_int ret = clSetEventCallback(m_event, status, callback, user_data);
236 if(ret != CL_SUCCESS){
237 BOOST_THROW_EXCEPTION(opencl_error(ret));
238 }
239 }
240
241 /// Registers a generic function to be called when the event status
242 /// changes to \p status (by default \c CL_COMPLETE).
243 ///
244 /// The function specified by \p callback must be invokable with zero
245 /// arguments (e.g. \c callback()).
246 ///
247 /// \opencl_version_warning{1,1}
248 template<class Function>
249 void set_callback(Function callback, cl_int status = CL_COMPLETE)
250 {
251 set_callback(
252 event_callback_invoker,
253 status,
254 new boost::function<void()>(callback)
255 );
256 }
257 #endif // CL_VERSION_1_1
258
259 /// Returns the total duration of the event from \p start to \p end.
260 ///
261 /// For example, to print the number of milliseconds the event took to
262 /// execute:
263 /// \code
264 /// std::cout << event.duration<std::chrono::milliseconds>().count() << " ms" << std::endl;
265 /// \endcode
266 ///
267 /// \see event::get_profiling_info()
268 template<class Duration>
269 Duration duration(cl_profiling_info start = CL_PROFILING_COMMAND_START,
270 cl_profiling_info end = CL_PROFILING_COMMAND_END) const
271 {
272 const ulong_ nanoseconds =
273 get_profiling_info<ulong_>(end) - get_profiling_info<ulong_>(start);
274
275 return detail::make_duration_from_nanoseconds(Duration(), nanoseconds);
276 }
277
278 /// Returns \c true if the event is the same as \p other.
279 bool operator==(const event &other) const
280 {
281 return m_event == other.m_event;
282 }
283
284 /// Returns \c true if the event is different from \p other.
285 bool operator!=(const event &other) const
286 {
287 return m_event != other.m_event;
288 }
289
290 /// \internal_
291 operator cl_event() const
292 {
293 return m_event;
294 }
295
296 /// \internal_ (deprecated)
297 cl_int get_status() const
298 {
299 return status();
300 }
301
302 private:
303 #ifdef CL_VERSION_1_1
304 /// \internal_
305 static void BOOST_COMPUTE_CL_CALLBACK
306 event_callback_invoker(cl_event, cl_int, void *user_data)
307 {
308 boost::function<void()> *callback =
309 static_cast<boost::function<void()> *>(user_data);
310
311 (*callback)();
312
313 delete callback;
314 }
315 #endif // CL_VERSION_1_1
316
317 protected:
318 cl_event m_event;
319 };
320
321 /// \internal_ define get_info() specializations for event
322 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event,
323 ((cl_command_queue, CL_EVENT_COMMAND_QUEUE))
324 ((cl_command_type, CL_EVENT_COMMAND_TYPE))
325 ((cl_int, CL_EVENT_COMMAND_EXECUTION_STATUS))
326 ((cl_uint, CL_EVENT_REFERENCE_COUNT))
327 )
328
329 #ifdef CL_VERSION_1_1
330 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event,
331 ((cl_context, CL_EVENT_CONTEXT))
332 )
333 #endif
334
335 } // end compute namespace
336 } // end boost namespace
337
338 #endif // BOOST_COMPUTE_EVENT_HPP