Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:44:39

0001 //---------------------------------------------------------------------------//
0002 // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
0003 //
0004 // Distributed under the Boost Software License, Version 1.0
0005 // See accompanying file LICENSE_1_0.txt or copy at
0006 // http://www.boost.org/LICENSE_1_0.txt
0007 //
0008 // See http://boostorg.github.com/compute for more information.
0009 //---------------------------------------------------------------------------//
0010 
0011 #ifndef BOOST_COMPUTE_EVENT_HPP
0012 #define BOOST_COMPUTE_EVENT_HPP
0013 
0014 #include <boost/function.hpp>
0015 
0016 #include <boost/compute/config.hpp>
0017 #include <boost/compute/exception.hpp>
0018 #include <boost/compute/detail/duration.hpp>
0019 #include <boost/compute/detail/get_object_info.hpp>
0020 #include <boost/compute/detail/assert_cl_success.hpp>
0021 #include <boost/compute/types/fundamental.hpp>
0022 
0023 namespace boost {
0024 namespace compute {
0025 
0026 /// \class event
0027 /// \brief An event corresponding to an operation on a compute device
0028 ///
0029 /// Event objects are used to track operations running on the device (such as
0030 /// kernel executions and memory transfers). Event objects are returned by the
0031 /// various \c enqueue_* methods of the command_queue class.
0032 ///
0033 /// Events can be used to synchronize operations between the host and the
0034 /// device. The \c wait() method will block execution on the host until the
0035 /// operation corresponding to the event on the device has completed. The
0036 /// status of the operation can also be polled with the \c status() method.
0037 ///
0038 /// Event objects can also be used for performance profiling. In order to use
0039 /// events for profiling, the command queue must be constructed with the
0040 /// \c CL_QUEUE_PROFILING_ENABLE flag. Then the \c duration() method can be
0041 /// used to retrieve the total duration of the operation on the device:
0042 /// \code
0043 /// std::cout << "time = " << e.duration<std::chrono::milliseconds>().count() << "ms\n";
0044 /// \endcode
0045 ///
0046 /// \see \ref future "future<T>", wait_list
0047 class event
0048 {
0049 public:
0050     /// \internal_
0051     enum execution_status {
0052         complete = CL_COMPLETE,
0053         running = CL_RUNNING,
0054         submitted = CL_SUBMITTED,
0055         queued = CL_QUEUED
0056     };
0057 
0058     /// \internal_
0059     enum command_type {
0060         ndrange_kernel = CL_COMMAND_NDRANGE_KERNEL,
0061         task = CL_COMMAND_TASK,
0062         native_kernel = CL_COMMAND_NATIVE_KERNEL,
0063         read_buffer = CL_COMMAND_READ_BUFFER,
0064         write_buffer = CL_COMMAND_WRITE_BUFFER,
0065         copy_buffer = CL_COMMAND_COPY_BUFFER,
0066         read_image = CL_COMMAND_READ_IMAGE,
0067         write_image = CL_COMMAND_WRITE_IMAGE,
0068         copy_image = CL_COMMAND_COPY_IMAGE,
0069         copy_image_to_buffer = CL_COMMAND_COPY_IMAGE_TO_BUFFER,
0070         copy_buffer_to_image = CL_COMMAND_COPY_BUFFER_TO_IMAGE,
0071         map_buffer = CL_COMMAND_MAP_BUFFER,
0072         map_image = CL_COMMAND_MAP_IMAGE,
0073         unmap_mem_object = CL_COMMAND_UNMAP_MEM_OBJECT,
0074         marker = CL_COMMAND_MARKER,
0075         aquire_gl_objects = CL_COMMAND_ACQUIRE_GL_OBJECTS,
0076         release_gl_object = CL_COMMAND_RELEASE_GL_OBJECTS
0077         #if defined(BOOST_COMPUTE_CL_VERSION_1_1)
0078         ,
0079         read_buffer_rect = CL_COMMAND_READ_BUFFER_RECT,
0080         write_buffer_rect = CL_COMMAND_WRITE_BUFFER_RECT,
0081         copy_buffer_rect = CL_COMMAND_COPY_BUFFER_RECT
0082         #endif
0083     };
0084 
0085     /// \internal_
0086     enum profiling_info {
0087         profiling_command_queued = CL_PROFILING_COMMAND_QUEUED,
0088         profiling_command_submit = CL_PROFILING_COMMAND_SUBMIT,
0089         profiling_command_start = CL_PROFILING_COMMAND_START,
0090         profiling_command_end = CL_PROFILING_COMMAND_END
0091     };
0092 
0093     /// Creates a null event object.
0094     event()
0095         : m_event(0)
0096     {
0097     }
0098 
0099     explicit event(cl_event event, bool retain = true)
0100         : m_event(event)
0101     {
0102         if(m_event && retain){
0103             clRetainEvent(event);
0104         }
0105     }
0106 
0107     /// Makes a new event as a copy of \p other.
0108     event(const event &other)
0109         : m_event(other.m_event)
0110     {
0111         if(m_event){
0112             clRetainEvent(m_event);
0113         }
0114     }
0115 
0116     /// Copies the event object from \p other to \c *this.
0117     event& operator=(const event &other)
0118     {
0119         if(this != &other){
0120             if(m_event){
0121                 clReleaseEvent(m_event);
0122             }
0123 
0124             m_event = other.m_event;
0125 
0126             if(m_event){
0127                 clRetainEvent(m_event);
0128             }
0129         }
0130 
0131         return *this;
0132     }
0133 
0134     #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
0135     /// Move-constructs a new event object from \p other.
0136     event(event&& other) BOOST_NOEXCEPT
0137         : m_event(other.m_event)
0138     {
0139         other.m_event = 0;
0140     }
0141 
0142     /// Move-assigns the event from \p other to \c *this.
0143     event& operator=(event&& other) BOOST_NOEXCEPT
0144     {
0145         if(m_event){
0146             clReleaseEvent(m_event);
0147         }
0148 
0149         m_event = other.m_event;
0150         other.m_event = 0;
0151 
0152         return *this;
0153     }
0154     #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
0155 
0156     /// Destroys the event object.
0157     ~event()
0158     {
0159         if(m_event){
0160             BOOST_COMPUTE_ASSERT_CL_SUCCESS(
0161                 clReleaseEvent(m_event)
0162             );
0163         }
0164     }
0165 
0166     /// Returns a reference to the underlying OpenCL event object.
0167     cl_event& get() const
0168     {
0169         return const_cast<cl_event &>(m_event);
0170     }
0171 
0172     /// Returns the status of the event.
0173     cl_int status() const
0174     {
0175         return get_info<cl_int>(CL_EVENT_COMMAND_EXECUTION_STATUS);
0176     }
0177 
0178     /// Returns the command type for the event.
0179     cl_command_type get_command_type() const
0180     {
0181         return get_info<cl_command_type>(CL_EVENT_COMMAND_TYPE);
0182     }
0183 
0184     /// Returns information about the event.
0185     ///
0186     /// \see_opencl_ref{clGetEventInfo}
0187     template<class T>
0188     T get_info(cl_event_info info) const
0189     {
0190         return detail::get_object_info<T>(clGetEventInfo, m_event, info);
0191     }
0192 
0193     /// \overload
0194     template<int Enum>
0195     typename detail::get_object_info_type<event, Enum>::type
0196     get_info() const;
0197 
0198     /// Returns profiling information for the event.
0199     ///
0200     /// \see event::duration()
0201     ///
0202     /// \see_opencl_ref{clGetEventProfilingInfo}
0203     template<class T>
0204     T get_profiling_info(cl_profiling_info info) const
0205     {
0206         return detail::get_object_info<T>(clGetEventProfilingInfo,
0207                                           m_event,
0208                                           info);
0209     }
0210 
0211     /// Blocks until the actions corresponding to the event have
0212     /// completed.
0213     void wait() const
0214     {
0215         cl_int ret = clWaitForEvents(1, &m_event);
0216         if(ret != CL_SUCCESS){
0217             BOOST_THROW_EXCEPTION(opencl_error(ret));
0218         }
0219     }
0220 
0221     #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
0222     /// Registers a function to be called when the event status changes to
0223     /// \p status (by default CL_COMPLETE). The callback is passed the OpenCL
0224     /// event object, the event status, and a pointer to arbitrary user data.
0225     ///
0226     /// \see_opencl_ref{clSetEventCallback}
0227     ///
0228     /// \opencl_version_warning{1,1}
0229     void set_callback(void (BOOST_COMPUTE_CL_CALLBACK *callback)(
0230                           cl_event event, cl_int status, void *user_data
0231                       ),
0232                       cl_int status = CL_COMPLETE,
0233                       void *user_data = 0)
0234     {
0235         cl_int ret = clSetEventCallback(m_event, status, callback, user_data);
0236         if(ret != CL_SUCCESS){
0237             BOOST_THROW_EXCEPTION(opencl_error(ret));
0238         }
0239     }
0240 
0241     /// Registers a generic function to be called when the event status
0242     /// changes to \p status (by default \c CL_COMPLETE).
0243     ///
0244     /// The function specified by \p callback must be invokable with zero
0245     /// arguments (e.g. \c callback()).
0246     ///
0247     /// \opencl_version_warning{1,1}
0248     template<class Function>
0249     void set_callback(Function callback, cl_int status = CL_COMPLETE)
0250     {
0251         set_callback(
0252             event_callback_invoker,
0253             status,
0254             new boost::function<void()>(callback)
0255         );
0256     }
0257     #endif // BOOST_COMPUTE_CL_VERSION_1_1
0258 
0259     /// Returns the total duration of the event from \p start to \p end.
0260     ///
0261     /// For example, to print the number of milliseconds the event took to
0262     /// execute:
0263     /// \code
0264     /// std::cout << event.duration<std::chrono::milliseconds>().count() << " ms" << std::endl;
0265     /// \endcode
0266     ///
0267     /// \see event::get_profiling_info()
0268     template<class Duration>
0269     Duration duration(cl_profiling_info start = CL_PROFILING_COMMAND_START,
0270                       cl_profiling_info end = CL_PROFILING_COMMAND_END) const
0271     {
0272         const ulong_ nanoseconds =
0273             get_profiling_info<ulong_>(end) - get_profiling_info<ulong_>(start);
0274 
0275         return detail::make_duration_from_nanoseconds(Duration(), nanoseconds);
0276     }
0277 
0278     /// Returns \c true if the event is the same as \p other.
0279     bool operator==(const event &other) const
0280     {
0281         return m_event == other.m_event;
0282     }
0283 
0284     /// Returns \c true if the event is different from \p other.
0285     bool operator!=(const event &other) const
0286     {
0287         return m_event != other.m_event;
0288     }
0289 
0290     /// \internal_
0291     operator cl_event() const
0292     {
0293         return m_event;
0294     }
0295 
0296     /// \internal_ (deprecated)
0297     cl_int get_status() const
0298     {
0299         return status();
0300     }
0301 
0302 private:
0303     #ifdef BOOST_COMPUTE_CL_VERSION_1_1
0304     /// \internal_
0305     static void BOOST_COMPUTE_CL_CALLBACK
0306     event_callback_invoker(cl_event, cl_int, void *user_data)
0307     {
0308         boost::function<void()> *callback =
0309             static_cast<boost::function<void()> *>(user_data);
0310 
0311         (*callback)();
0312 
0313         delete callback;
0314     }
0315     #endif // BOOST_COMPUTE_CL_VERSION_1_1
0316 
0317 protected:
0318     cl_event m_event;
0319 };
0320 
0321 /// \internal_ define get_info() specializations for event
0322 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event,
0323     ((cl_command_queue, CL_EVENT_COMMAND_QUEUE))
0324     ((cl_command_type, CL_EVENT_COMMAND_TYPE))
0325     ((cl_int, CL_EVENT_COMMAND_EXECUTION_STATUS))
0326     ((cl_uint, CL_EVENT_REFERENCE_COUNT))
0327 )
0328 
0329 #ifdef BOOST_COMPUTE_CL_VERSION_1_1
0330 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event,
0331     ((cl_context, CL_EVENT_CONTEXT))
0332 )
0333 #endif
0334 
0335 } // end compute namespace
0336 } // end boost namespace
0337 
0338 #endif // BOOST_COMPUTE_EVENT_HPP