17 #include <Kokkos_Macros.hpp>
19 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
21 "Including non-public Kokkos header files is not allowed.");
24 #ifndef KOKKOS_ENABLE_DEPRECATED_CODE_4
25 #error "The tasking framework is deprecated"
28 #ifndef KOKKOS_FUTURE_HPP
29 #define KOKKOS_FUTURE_HPP
33 #include <Kokkos_Macros.hpp>
34 #if defined(KOKKOS_ENABLE_TASKDAG)
36 #include <Kokkos_Core_fwd.hpp>
37 #include <Kokkos_TaskScheduler_fwd.hpp>
40 #include <impl/Kokkos_TaskQueue.hpp>
41 #include <impl/Kokkos_TaskResult.hpp>
42 #include <impl/Kokkos_TaskBase.hpp>
43 #include <Kokkos_Atomic.hpp>
45 #include <Kokkos_Concepts.hpp>
50 #ifdef KOKKOS_ENABLE_DEPRECATION_WARNINGS
52 KOKKOS_IMPL_DISABLE_DEPRECATED_WARNINGS_PUSH()
60 template <
typename ValueType,
typename ExecutionSpace,
typename QueueType>
61 class KOKKOS_DEPRECATED
62 BasicFuture<ValueType, SimpleTaskScheduler<ExecutionSpace, QueueType>> {
64 using value_type = ValueType;
65 using execution_space = ExecutionSpace;
66 using scheduler_type = SimpleTaskScheduler<ExecutionSpace, QueueType>;
67 using queue_type =
typename scheduler_type::task_queue_type;
70 template <
class,
class>
71 friend class SimpleTaskScheduler;
72 template <
class,
class>
73 friend class BasicFuture;
75 using task_base_type =
typename scheduler_type::task_base_type;
76 using task_queue_type =
typename scheduler_type::task_queue_type;
78 using task_queue_traits =
typename scheduler_type::task_queue_traits;
79 using task_scheduling_info_type =
80 typename scheduler_type::task_scheduling_info_type;
82 using result_storage_type = Impl::TaskResultStorage<
84 Impl::SchedulingInfoStorage<Impl::RunnableTaskBase<task_queue_traits>,
85 task_scheduling_info_type>>;
87 OwningRawPtr<task_base_type> m_task =
nullptr;
89 KOKKOS_INLINE_FUNCTION
90 explicit BasicFuture(task_base_type* task) : m_task(task) {
97 KOKKOS_INLINE_FUNCTION
98 BasicFuture() noexcept : m_task(
nullptr) {}
100 KOKKOS_INLINE_FUNCTION
101 BasicFuture(BasicFuture&& rhs) noexcept : m_task(std::move(rhs.m_task)) {
102 rhs.m_task =
nullptr;
105 KOKKOS_INLINE_FUNCTION
106 BasicFuture(BasicFuture
const& rhs)
109 *
static_cast<task_base_type* volatile*
>(&m_task) = rhs.m_task;
110 if (m_task) m_task->increment_reference_count();
113 KOKKOS_INLINE_FUNCTION
114 BasicFuture& operator=(BasicFuture&& rhs) noexcept {
115 if (m_task != rhs.m_task) {
118 *
static_cast<task_base_type* volatile*
>(&m_task) = rhs.m_task;
124 rhs.m_task =
nullptr;
128 KOKKOS_INLINE_FUNCTION
129 BasicFuture& operator=(BasicFuture
const& rhs) {
130 if (m_task != rhs.m_task) {
133 *
static_cast<task_base_type* volatile*
>(&m_task) = rhs.m_task;
135 if (m_task !=
nullptr) {
136 m_task->increment_reference_count();
143 template <
class T,
class S>
144 KOKKOS_INLINE_FUNCTION BasicFuture(
145 BasicFuture<T, S>&& rhs) noexcept
146 : m_task(std::move(rhs.m_task)) {
148 std::is_void_v<scheduler_type> || std::is_same_v<scheduler_type, S>,
149 "Moved Futures must have the same scheduler");
151 static_assert(std::is_void_v<value_type> || std::is_same_v<value_type, T>,
152 "Moved Futures must have the same value_type");
155 rhs.m_task =
nullptr;
158 template <
class T,
class S>
159 KOKKOS_INLINE_FUNCTION BasicFuture(
160 BasicFuture<T, S>
const& rhs)
164 std::is_void_v<scheduler_type> || std::is_same_v<scheduler_type, S>,
165 "Copied Futures must have the same scheduler");
167 static_assert(std::is_void_v<value_type> || std::is_same_v<value_type, T>,
168 "Copied Futures must have the same value_type");
170 *
static_cast<task_base_type* volatile*
>(&m_task) = rhs.m_task;
171 if (m_task) m_task->increment_reference_count();
174 template <
class T,
class S>
175 KOKKOS_INLINE_FUNCTION BasicFuture& operator=(BasicFuture<T, S>
const& rhs) {
177 std::is_void_v<scheduler_type> || std::is_same_v<scheduler_type, S>,
178 "Assigned Futures must have the same scheduler");
180 static_assert(std::is_void_v<value_type> || std::is_same_v<value_type, T>,
181 "Assigned Futures must have the same value_type");
183 if (m_task != rhs.m_task) {
186 *
static_cast<task_base_type* volatile*
>(&m_task) = rhs.m_task;
187 if (m_task !=
nullptr) {
188 m_task->increment_reference_count();
194 template <
class T,
class S>
195 KOKKOS_INLINE_FUNCTION BasicFuture& operator=(BasicFuture<T, S>&& rhs) {
197 std::is_void_v<scheduler_type> || std::is_same_v<scheduler_type, S>,
198 "Assigned Futures must have the same scheduler");
200 static_assert(std::is_void_v<value_type> || std::is_same_v<value_type, T>,
201 "Assigned Futures must have the same value_type");
203 if (m_task != rhs.m_task) {
206 *
static_cast<task_base_type* volatile*
>(&m_task) = rhs.m_task;
212 rhs.m_task =
nullptr;
216 KOKKOS_INLINE_FUNCTION
217 ~BasicFuture() noexcept { clear(); }
221 KOKKOS_INLINE_FUNCTION
222 void clear() noexcept {
224 bool should_delete = m_task->decrement_and_check_reference_count();
226 static_cast<task_queue_type*
>(m_task->ready_queue_base_ptr())
227 ->deallocate(std::move(*m_task));
231 *
static_cast<task_base_type* volatile*
>(&m_task) =
nullptr;
234 KOKKOS_INLINE_FUNCTION
235 bool is_null() const noexcept {
return m_task ==
nullptr; }
237 KOKKOS_INLINE_FUNCTION
238 bool is_ready() const noexcept {
239 return (m_task ==
nullptr) || m_task->wait_queue_is_consumed();
242 KOKKOS_INLINE_FUNCTION
243 const typename Impl::TaskResult<ValueType>::reference_type
get()
const {
244 KOKKOS_EXPECTS(is_ready());
245 return static_cast<result_storage_type*
>(m_task)->value_reference();
254 template <
typename ValueType,
typename Scheduler>
255 class KOKKOS_DEPRECATED BasicFuture {
257 template <
typename,
typename>
258 friend class BasicTaskScheduler;
259 template <
typename,
typename>
260 friend class BasicFuture;
261 friend class Impl::TaskBase;
262 template <
typename,
typename,
typename>
263 friend class Impl::Task;
270 using scheduler_type = Scheduler;
271 using queue_type =
typename scheduler_type::queue_type;
272 using execution_space =
typename scheduler_type::execution_space;
273 using value_type = ValueType;
280 using task_base = Impl::TaskBase;
284 KOKKOS_INLINE_FUNCTION
explicit BasicFuture(task_base* task)
286 if (task) queue_type::assign(&m_task, task);
294 KOKKOS_INLINE_FUNCTION
295 bool is_null()
const {
return nullptr == m_task; }
297 KOKKOS_INLINE_FUNCTION
298 int reference_count()
const {
299 return nullptr != m_task ? m_task->reference_count() : 0;
304 KOKKOS_INLINE_FUNCTION
306 if (m_task) queue_type::assign(&m_task,
nullptr);
311 KOKKOS_INLINE_FUNCTION
312 ~BasicFuture() { clear(); }
316 KOKKOS_INLINE_FUNCTION
317 BasicFuture() noexcept : m_task(
nullptr) {}
319 KOKKOS_INLINE_FUNCTION
320 BasicFuture(BasicFuture&& rhs) noexcept : m_task(rhs.m_task) {
321 rhs.m_task =
nullptr;
324 KOKKOS_INLINE_FUNCTION
325 BasicFuture(
const BasicFuture& rhs) : m_task(nullptr) {
326 if (rhs.m_task) queue_type::assign(&m_task, rhs.m_task);
329 KOKKOS_INLINE_FUNCTION
330 BasicFuture& operator=(BasicFuture&& rhs) noexcept {
333 rhs.m_task =
nullptr;
337 KOKKOS_INLINE_FUNCTION
338 BasicFuture& operator=(BasicFuture
const& rhs) {
339 if (&rhs ==
this)
return *
this;
340 if (m_task || rhs.m_task) queue_type::assign(&m_task, rhs.m_task);
346 template <
class T,
class S>
347 KOKKOS_INLINE_FUNCTION BasicFuture(
348 BasicFuture<T, S>&& rhs) noexcept
349 : m_task(rhs.m_task) {
351 std::is_void_v<scheduler_type> || std::is_same_v<scheduler_type, S>,
352 "Assigned Futures must have the same scheduler");
354 static_assert(std::is_void_v<value_type> || std::is_same_v<value_type, T>,
355 "Assigned Futures must have the same value_type");
360 template <
class T,
class S>
361 KOKKOS_INLINE_FUNCTION BasicFuture(
362 BasicFuture<T, S>
const& rhs)
365 std::is_void_v<scheduler_type> || std::is_same_v<scheduler_type, S>,
366 "Assigned Futures must have the same scheduler");
368 static_assert(std::is_void_v<value_type> || std::is_same_v<value_type, T>,
369 "Assigned Futures must have the same value_type");
371 if (rhs.m_task) queue_type::assign(&m_task, rhs.m_task);
374 template <
class T,
class S>
375 KOKKOS_INLINE_FUNCTION BasicFuture& operator=(BasicFuture<T, S>
const& rhs) {
377 std::is_void_v<scheduler_type> || std::is_same_v<scheduler_type, S>,
378 "Assigned Futures must have the same scheduler");
380 static_assert(std::is_void_v<value_type> || std::is_same_v<value_type, T>,
381 "Assigned Futures must have the same value_type");
383 if (m_task || rhs.m_task) queue_type::assign(&m_task, rhs.m_task);
387 template <
class T,
class S>
388 KOKKOS_INLINE_FUNCTION BasicFuture& operator=(BasicFuture<T, S>&& rhs) {
390 std::is_void_v<scheduler_type> || std::is_same_v<scheduler_type, S>,
391 "Assigned Futures must have the same scheduler");
393 static_assert(std::is_void_v<value_type> || std::is_same_v<value_type, T>,
394 "Assigned Futures must have the same value_type");
404 KOKKOS_INLINE_FUNCTION
405 int is_ready() const noexcept {
406 return (
nullptr == m_task) ||
407 (
reinterpret_cast<task_base*
>(task_base::LockTag) == m_task->m_wait);
410 KOKKOS_INLINE_FUNCTION
411 const typename Impl::TaskResult<ValueType>::reference_type
get()
const {
412 if (
nullptr == m_task) {
413 Kokkos::abort(
"Kokkos:::Future::get ERROR: is_null()");
415 return Impl::TaskResult<ValueType>::get(m_task);
420 template <
typename,
typename ExecSpace =
void>
421 struct KOKKOS_DEPRECATED is_future :
public std::false_type {};
423 template <
typename ValueType,
typename Scheduler,
typename ExecSpace>
424 struct KOKKOS_DEPRECATED is_future<BasicFuture<ValueType, Scheduler>, ExecSpace>
425 : std::bool_constant<
426 std::is_same_v<ExecSpace, typename Scheduler::execution_space> ||
427 std::is_void_v<ExecSpace>> {};
435 template <
class Arg1,
class Arg2>
436 class ResolveFutureArgOrder {
438 enum { Arg1_is_space = Kokkos::is_space<Arg1>::value };
439 enum { Arg2_is_space = Kokkos::is_space<Arg2>::value };
440 enum { Arg1_is_value = !Arg1_is_space && !std::is_void_v<Arg1> };
441 enum { Arg2_is_value = !Arg2_is_space && !std::is_void_v<Arg2> };
443 static_assert(!(Arg1_is_space && Arg2_is_space),
444 "Future cannot be given two spaces");
446 static_assert(!(Arg1_is_value && Arg2_is_value),
447 "Future cannot be given two value types");
450 std::conditional_t<Arg1_is_value, Arg1,
451 std::conditional_t<Arg2_is_value, Arg2, void>>;
453 using execution_space =
typename std::conditional_t<
455 std::conditional_t<Arg2_is_space, Arg2, void>>::execution_space;
458 using type = BasicFuture<value_type, TaskScheduler<execution_space>>;
470 template <
class Arg1 =
void,
class Arg2 =
void>
471 using Future KOKKOS_DEPRECATED =
472 typename Impl::ResolveFutureArgOrder<Arg1, Arg2>::type;
476 #ifdef KOKKOS_ENABLE_DEPRECATION_WARNINGS
477 KOKKOS_IMPL_DISABLE_DEPRECATED_WARNINGS_POP()
bool is_null(const boost::shared_ptr< T > &p)