• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2013-2014 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 #define BOOST_TEST_MODULE TestEvent
12 #include <boost/test/unit_test.hpp>
13 
14 #include <vector>
15 
16 #ifdef BOOST_COMPUTE_USE_CPP11
17 #include <mutex>
18 #include <future>
19 #endif // BOOST_COMPUTE_USE_CPP11
20 
21 #include <boost/compute/async/future.hpp>
22 #include <boost/compute/event.hpp>
23 
24 #include "context_setup.hpp"
25 
BOOST_AUTO_TEST_CASE(null_event)26 BOOST_AUTO_TEST_CASE(null_event)
27 {
28     boost::compute::event null;
29     BOOST_CHECK(null.get() == cl_event());
30 }
31 
32 #if defined(BOOST_COMPUTE_CL_VERSION_1_1) && defined(BOOST_COMPUTE_USE_CPP11)
33 std::mutex callback_mutex;
34 std::condition_variable callback_condition_variable;
35 static bool callback_invoked = false;
36 
37 static void BOOST_COMPUTE_CL_CALLBACK
callback(cl_event event,cl_int status,void * user_data)38 callback(cl_event event, cl_int status, void *user_data)
39 {
40     std::lock_guard<std::mutex> lock(callback_mutex);
41     callback_invoked = true;
42     callback_condition_variable.notify_one();
43 }
44 
BOOST_AUTO_TEST_CASE(event_callback)45 BOOST_AUTO_TEST_CASE(event_callback)
46 {
47     REQUIRES_OPENCL_VERSION(1,2);
48 
49     // ensure callback has not yet been executed
50     BOOST_CHECK_EQUAL(callback_invoked, false);
51 
52     // enqueue marker and set callback to be invoked
53     boost::compute::event marker = queue.enqueue_marker();
54     marker.set_callback(callback);
55     marker.wait();
56 
57     // wait up to one second for the callback to be executed
58     std::unique_lock<std::mutex> lock(callback_mutex);
59     callback_condition_variable.wait_for(
60         lock, std::chrono::seconds(1), [&](){ return callback_invoked; }
61     );
62 
63     // ensure callback has been executed
64     BOOST_CHECK_EQUAL(callback_invoked, true);
65 }
66 
BOOST_AUTO_TEST_CASE(lambda_callback)67 BOOST_AUTO_TEST_CASE(lambda_callback)
68 {
69     REQUIRES_OPENCL_VERSION(1,2);
70 
71     bool lambda_invoked = false;
72 
73     boost::compute::event marker = queue.enqueue_marker();
74     marker.set_callback([&](){
75         std::lock_guard<std::mutex> lock(callback_mutex);
76         lambda_invoked = true;
77         callback_condition_variable.notify_one();
78     });
79     marker.wait();
80 
81     // wait up to one second for the callback to be executed
82     std::unique_lock<std::mutex> lock(callback_mutex);
83     callback_condition_variable.wait_for(
84         lock, std::chrono::seconds(1), [&](){ return lambda_invoked; }
85     );
86     BOOST_CHECK_EQUAL(lambda_invoked, true);
87 }
88 
BOOST_AUTO_TEST_CASE(future_then_callback)89 BOOST_AUTO_TEST_CASE(future_then_callback)
90 {
91     REQUIRES_OPENCL_VERSION(1,2);
92 
93     bool callback_invoked = false;
94 
95     boost::compute::future<void> future(queue.enqueue_marker());
96     future.then([&](){
97         std::lock_guard<std::mutex> lock(callback_mutex);
98         callback_invoked = true;
99         callback_condition_variable.notify_one();
100     });
101     future.wait();
102 
103     // wait up to one second for the callback to be executed
104     std::unique_lock<std::mutex> lock(callback_mutex);
105     callback_condition_variable.wait_for(
106         lock, std::chrono::seconds(1), [&](){ return callback_invoked; }
107     );
108     BOOST_CHECK_EQUAL(callback_invoked, true);
109 }
110 
111 void BOOST_COMPUTE_CL_CALLBACK
event_promise_fulfiller_callback(cl_event event,cl_int status,void * user_data)112 event_promise_fulfiller_callback(cl_event event, cl_int status, void *user_data)
113 {
114     auto *promise = static_cast<std::promise<void> *>(user_data);
115     promise->set_value();
116     delete promise;
117 }
118 
BOOST_AUTO_TEST_CASE(event_to_std_future)119 BOOST_AUTO_TEST_CASE(event_to_std_future)
120 {
121     REQUIRES_OPENCL_VERSION(1,2);
122 
123     // enqueue an asynchronous copy to the device
124     std::vector<float> vector(1000, 3.14f);
125     boost::compute::buffer buffer(context, 1000 * sizeof(float));
126     auto event = queue.enqueue_write_buffer_async(
127         buffer, 0, 1000 * sizeof(float), vector.data()
128     );
129 
130     // create a promise and future to be set by the callback
131     auto *promise = new std::promise<void>;
132     std::future<void> future = promise->get_future();
133     event.set_callback(event_promise_fulfiller_callback, CL_COMPLETE, promise);
134 
135     // ensure commands are submitted to the device before waiting
136     queue.flush();
137 
138     // wait for future to become ready
139     future.wait();
140 }
141 #endif // BOOST_COMPUTE_CL_VERSION_1_1
142 
143 BOOST_AUTO_TEST_SUITE_END()
144