diff --git a/doc/reference.qbk b/doc/reference.qbk index 4f573d38..b3791aa9 100644 --- a/doc/reference.qbk +++ b/doc/reference.qbk @@ -114,6 +114,7 @@ Header: `` * [classref boost::compute::future future] * [funcref boost::compute::wait_for_all wait_for_all()] +* [classref boost::compute::wait_guard wait_guard] [h3 Containers] diff --git a/include/boost/compute/async.hpp b/include/boost/compute/async.hpp index 5a422002..30d7beb7 100644 --- a/include/boost/compute/async.hpp +++ b/include/boost/compute/async.hpp @@ -16,5 +16,6 @@ /// Meta-header to include all Boost.Compute async headers. #include +#include #endif // BOOST_COMPUTE_ASYNC_HPP diff --git a/include/boost/compute/async/wait_guard.hpp b/include/boost/compute/async/wait_guard.hpp new file mode 100644 index 00000000..03466b87 --- /dev/null +++ b/include/boost/compute/async/wait_guard.hpp @@ -0,0 +1,61 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2015 Kyle Lutz +// +// 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://kylelutz.github.com/compute for more information. +//---------------------------------------------------------------------------// + +#ifndef BOOST_COMPUTE_ASYNC_WAIT_GUARD_HPP +#define BOOST_COMPUTE_ASYNC_WAIT_GUARD_HPP + +namespace boost { +namespace compute { + +/// \class wait_guard +/// \brief A guard object for synchronizing an operation on the device +/// +/// The wait_guard class stores a waitable object representing an operation +/// on a compute device (e.g. \ref event, \ref future "future") and calls +/// its \c wait() method when the guard object goes out of scope. +/// +/// This is useful for ensuring that an OpenCL operation completes before +/// leaving the current scope and cleaning up any resources. +/// +/// For example: +/// \code +/// // enqueue a compute kernel for execution +/// event e = queue.enqueue_nd_range_kernel(...); +/// +/// // call e.wait() upon exiting the current scope +/// wait_guard guard(e); +/// \endcode +/// +/// \ref wait_list, wait_for_all() +template +class wait_guard : boost::noncopyable +{ +public: + /// Creates a new wait_guard object for \p waitable. + wait_guard(const Waitable &waitable) + : m_waitable(waitable) + { + } + + /// Destroys the wait_guard object. The default implementation will call + /// \c wait() on the stored waitable object. + ~wait_guard() + { + m_waitable.wait(); + } + +private: + Waitable m_waitable; +}; + +} // end compute namespace +} // end boost namespace + +#endif // BOOST_COMPUTE_ASYNC_WAIT_GUARD_HPP diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index fb1828ec..234377c0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -129,6 +129,7 @@ add_compute_test("allocator.buffer_allocator" test_buffer_allocator.cpp) add_compute_test("allocator.pinned_allocator" test_pinned_allocator.cpp) add_compute_test("async.wait" test_async_wait.cpp) +add_compute_test("async.wait_guard" test_async_wait_guard.cpp) add_compute_test("container.array" test_array.cpp) add_compute_test("container.dynamic_bitset" test_dynamic_bitset.cpp) diff --git a/test/test_async_wait_guard.cpp b/test/test_async_wait_guard.cpp new file mode 100644 index 00000000..ddedc1be --- /dev/null +++ b/test/test_async_wait_guard.cpp @@ -0,0 +1,41 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2013-2015 Kyle Lutz +// +// 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://kylelutz.github.com/compute for more information. +//---------------------------------------------------------------------------// + +#define BOOST_TEST_MODULE TestAsyncWaitGuard +#include + +#include +#include +#include +#include +#include + +#include "check_macros.hpp" +#include "context_setup.hpp" + +namespace compute = boost::compute; + +BOOST_AUTO_TEST_CASE(wait_for_fill) +{ + compute::vector vector(8192, context); + + compute::event fill_event = + compute::fill_async(vector.begin(), vector.end(), 9, queue).get_event(); + + BOOST_CHECK(fill_event.status() != CL_COMPLETE); + + { + compute::wait_guard fill_guard(fill_event); + } + + BOOST_CHECK(fill_event.status() == CL_COMPLETE); +} + +BOOST_AUTO_TEST_SUITE_END()