| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 | //---------------------------------------------------------------------------//// Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>//// Distributed under the Boost Software License, Version 1.0// See accompanying file LICENSE_1_0.txt or copy at// http://www.boost.org/LICENSE_1_0.txt//// See http://boostorg.github.com/compute for more information.//---------------------------------------------------------------------------//#ifndef BOOST_COMPUTE_EVENT_HPP#define BOOST_COMPUTE_EVENT_HPP#include <boost/function.hpp>#include <boost/compute/config.hpp>#include <boost/compute/exception.hpp>#include <boost/compute/detail/duration.hpp>#include <boost/compute/detail/get_object_info.hpp>#include <boost/compute/detail/assert_cl_success.hpp>#include <boost/compute/types/fundamental.hpp>namespace boost {namespace compute {/// \class event/// \brief An event corresponding to an operation on a compute device////// Event objects are used to track operations running on the device (such as/// kernel executions and memory transfers). Event objects are returned by the/// various \c enqueue_* methods of the command_queue class.////// Events can be used to synchronize operations between the host and the/// device. The \c wait() method will block execution on the host until the/// operation corresponding to the event on the device has completed. The/// status of the operation can also be polled with the \c status() method.////// Event objects can also be used for performance profiling. In order to use/// events for profiling, the command queue must be constructed with the/// \c CL_QUEUE_PROFILING_ENABLE flag. Then the \c duration() method can be/// used to retrieve the total duration of the operation on the device:/// \code/// std::cout << "time = " << e.duration<std::chrono::milliseconds>().count() << "ms\n";/// \endcode////// \see \ref future "future<T>", wait_listclass event{public:    /// \internal_    enum execution_status {        complete = CL_COMPLETE,        running = CL_RUNNING,        submitted = CL_SUBMITTED,        queued = CL_QUEUED    };    /// \internal_    enum command_type {        ndrange_kernel = CL_COMMAND_NDRANGE_KERNEL,        task = CL_COMMAND_TASK,        native_kernel = CL_COMMAND_NATIVE_KERNEL,        read_buffer = CL_COMMAND_READ_BUFFER,        write_buffer = CL_COMMAND_WRITE_BUFFER,        copy_buffer = CL_COMMAND_COPY_BUFFER,        read_image = CL_COMMAND_READ_IMAGE,        write_image = CL_COMMAND_WRITE_IMAGE,        copy_image = CL_COMMAND_COPY_IMAGE,        copy_image_to_buffer = CL_COMMAND_COPY_IMAGE_TO_BUFFER,        copy_buffer_to_image = CL_COMMAND_COPY_BUFFER_TO_IMAGE,        map_buffer = CL_COMMAND_MAP_BUFFER,        map_image = CL_COMMAND_MAP_IMAGE,        unmap_mem_object = CL_COMMAND_UNMAP_MEM_OBJECT,        marker = CL_COMMAND_MARKER,        aquire_gl_objects = CL_COMMAND_ACQUIRE_GL_OBJECTS,        release_gl_object = CL_COMMAND_RELEASE_GL_OBJECTS        #if defined(BOOST_COMPUTE_CL_VERSION_1_1)        ,        read_buffer_rect = CL_COMMAND_READ_BUFFER_RECT,        write_buffer_rect = CL_COMMAND_WRITE_BUFFER_RECT,        copy_buffer_rect = CL_COMMAND_COPY_BUFFER_RECT        #endif    };    /// \internal_    enum profiling_info {        profiling_command_queued = CL_PROFILING_COMMAND_QUEUED,        profiling_command_submit = CL_PROFILING_COMMAND_SUBMIT,        profiling_command_start = CL_PROFILING_COMMAND_START,        profiling_command_end = CL_PROFILING_COMMAND_END    };    /// Creates a null event object.    event()        : m_event(0)    {    }    explicit event(cl_event event, bool retain = true)        : m_event(event)    {        if(m_event && retain){            clRetainEvent(event);        }    }    /// Makes a new event as a copy of \p other.    event(const event &other)        : m_event(other.m_event)    {        if(m_event){            clRetainEvent(m_event);        }    }    /// Copies the event object from \p other to \c *this.    event& operator=(const event &other)    {        if(this != &other){            if(m_event){                clReleaseEvent(m_event);            }            m_event = other.m_event;            if(m_event){                clRetainEvent(m_event);            }        }        return *this;    }    #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES    /// Move-constructs a new event object from \p other.    event(event&& other) BOOST_NOEXCEPT        : m_event(other.m_event)    {        other.m_event = 0;    }    /// Move-assigns the event from \p other to \c *this.    event& operator=(event&& other) BOOST_NOEXCEPT    {        if(m_event){            clReleaseEvent(m_event);        }        m_event = other.m_event;        other.m_event = 0;        return *this;    }    #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES    /// Destroys the event object.    ~event()    {        if(m_event){            BOOST_COMPUTE_ASSERT_CL_SUCCESS(                clReleaseEvent(m_event)            );        }    }    /// Returns a reference to the underlying OpenCL event object.    cl_event& get() const    {        return const_cast<cl_event &>(m_event);    }    /// Returns the status of the event.    cl_int status() const    {        return get_info<cl_int>(CL_EVENT_COMMAND_EXECUTION_STATUS);    }    /// Returns the command type for the event.    cl_command_type get_command_type() const    {        return get_info<cl_command_type>(CL_EVENT_COMMAND_TYPE);    }    /// Returns information about the event.    ///    /// \see_opencl_ref{clGetEventInfo}    template<class T>    T get_info(cl_event_info info) const    {        return detail::get_object_info<T>(clGetEventInfo, m_event, info);    }    /// \overload    template<int Enum>    typename detail::get_object_info_type<event, Enum>::type    get_info() const;    /// Returns profiling information for the event.    ///    /// \see event::duration()    ///    /// \see_opencl_ref{clGetEventProfilingInfo}    template<class T>    T get_profiling_info(cl_profiling_info info) const    {        return detail::get_object_info<T>(clGetEventProfilingInfo,                                          m_event,                                          info);    }    /// Blocks until the actions corresponding to the event have    /// completed.    void wait() const    {        cl_int ret = clWaitForEvents(1, &m_event);        if(ret != CL_SUCCESS){            BOOST_THROW_EXCEPTION(opencl_error(ret));        }    }    #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)    /// Registers a function to be called when the event status changes to    /// \p status (by default CL_COMPLETE). The callback is passed the OpenCL    /// event object, the event status, and a pointer to arbitrary user data.    ///    /// \see_opencl_ref{clSetEventCallback}    ///    /// \opencl_version_warning{1,1}    void set_callback(void (BOOST_COMPUTE_CL_CALLBACK *callback)(                          cl_event event, cl_int status, void *user_data                      ),                      cl_int status = CL_COMPLETE,                      void *user_data = 0)    {        cl_int ret = clSetEventCallback(m_event, status, callback, user_data);        if(ret != CL_SUCCESS){            BOOST_THROW_EXCEPTION(opencl_error(ret));        }    }    /// Registers a generic function to be called when the event status    /// changes to \p status (by default \c CL_COMPLETE).    ///    /// The function specified by \p callback must be invokable with zero    /// arguments (e.g. \c callback()).    ///    /// \opencl_version_warning{1,1}    template<class Function>    void set_callback(Function callback, cl_int status = CL_COMPLETE)    {        set_callback(            event_callback_invoker,            status,            new boost::function<void()>(callback)        );    }    #endif // BOOST_COMPUTE_CL_VERSION_1_1    /// Returns the total duration of the event from \p start to \p end.    ///    /// For example, to print the number of milliseconds the event took to    /// execute:    /// \code    /// std::cout << event.duration<std::chrono::milliseconds>().count() << " ms" << std::endl;    /// \endcode    ///    /// \see event::get_profiling_info()    template<class Duration>    Duration duration(cl_profiling_info start = CL_PROFILING_COMMAND_START,                      cl_profiling_info end = CL_PROFILING_COMMAND_END) const    {        const ulong_ nanoseconds =            get_profiling_info<ulong_>(end) - get_profiling_info<ulong_>(start);        return detail::make_duration_from_nanoseconds(Duration(), nanoseconds);    }    /// Returns \c true if the event is the same as \p other.    bool operator==(const event &other) const    {        return m_event == other.m_event;    }    /// Returns \c true if the event is different from \p other.    bool operator!=(const event &other) const    {        return m_event != other.m_event;    }    /// \internal_    operator cl_event() const    {        return m_event;    }    /// \internal_ (deprecated)    cl_int get_status() const    {        return status();    }private:    #ifdef BOOST_COMPUTE_CL_VERSION_1_1    /// \internal_    static void BOOST_COMPUTE_CL_CALLBACK    event_callback_invoker(cl_event, cl_int, void *user_data)    {        boost::function<void()> *callback =            static_cast<boost::function<void()> *>(user_data);        (*callback)();        delete callback;    }    #endif // BOOST_COMPUTE_CL_VERSION_1_1protected:    cl_event m_event;};/// \internal_ define get_info() specializations for eventBOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event,    ((cl_command_queue, CL_EVENT_COMMAND_QUEUE))    ((cl_command_type, CL_EVENT_COMMAND_TYPE))    ((cl_int, CL_EVENT_COMMAND_EXECUTION_STATUS))    ((cl_uint, CL_EVENT_REFERENCE_COUNT)))#ifdef BOOST_COMPUTE_CL_VERSION_1_1BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(event,    ((cl_context, CL_EVENT_CONTEXT)))#endif} // end compute namespace} // end boost namespace#endif // BOOST_COMPUTE_EVENT_HPP
 |