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>
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)) {
147 static_assert(std::is_void<scheduler_type>::value ||
148 std::is_same<scheduler_type, S>::value,
149 "Moved Futures must have the same scheduler");
152 std::is_void<value_type>::value || std::is_same<value_type, T>::value,
153 "Moved Futures must have the same value_type");
156 rhs.m_task =
nullptr;
159 template <
class T,
class S>
160 KOKKOS_INLINE_FUNCTION BasicFuture(
161 BasicFuture<T, S>
const& rhs)
164 static_assert(std::is_void<scheduler_type>::value ||
165 std::is_same<scheduler_type, S>::value,
166 "Copied Futures must have the same scheduler");
169 std::is_void<value_type>::value || std::is_same<value_type, T>::value,
170 "Copied Futures must have the same value_type");
172 *
static_cast<task_base_type* volatile*
>(&m_task) = rhs.m_task;
173 if (m_task) m_task->increment_reference_count();
176 template <
class T,
class S>
177 KOKKOS_INLINE_FUNCTION BasicFuture& operator=(BasicFuture<T, S>
const& rhs) {
178 static_assert(std::is_void<scheduler_type>::value ||
179 std::is_same<scheduler_type, S>::value,
180 "Assigned Futures must have the same scheduler");
183 std::is_void<value_type>::value || std::is_same<value_type, T>::value,
184 "Assigned Futures must have the same value_type");
186 if (m_task != rhs.m_task) {
189 *
static_cast<task_base_type* volatile*
>(&m_task) = rhs.m_task;
190 if (m_task !=
nullptr) {
191 m_task->increment_reference_count();
197 template <
class T,
class S>
198 KOKKOS_INLINE_FUNCTION BasicFuture& operator=(BasicFuture<T, S>&& rhs) {
199 static_assert(std::is_void<scheduler_type>::value ||
200 std::is_same<scheduler_type, S>::value,
201 "Assigned Futures must have the same scheduler");
204 std::is_void<value_type>::value || std::is_same<value_type, T>::value,
205 "Assigned Futures must have the same value_type");
207 if (m_task != rhs.m_task) {
210 *
static_cast<task_base_type* volatile*
>(&m_task) = rhs.m_task;
216 rhs.m_task =
nullptr;
220 KOKKOS_INLINE_FUNCTION
221 ~BasicFuture() noexcept { clear(); }
225 KOKKOS_INLINE_FUNCTION
226 void clear() noexcept {
228 bool should_delete = m_task->decrement_and_check_reference_count();
230 static_cast<task_queue_type*
>(m_task->ready_queue_base_ptr())
231 ->deallocate(std::move(*m_task));
235 *
static_cast<task_base_type* volatile*
>(&m_task) =
nullptr;
238 KOKKOS_INLINE_FUNCTION
239 bool is_null() const noexcept {
return m_task ==
nullptr; }
241 KOKKOS_INLINE_FUNCTION
242 bool is_ready() const noexcept {
243 return (m_task ==
nullptr) || m_task->wait_queue_is_consumed();
246 KOKKOS_INLINE_FUNCTION
247 const typename Impl::TaskResult<ValueType>::reference_type
get()
const {
248 KOKKOS_EXPECTS(is_ready());
249 return static_cast<result_storage_type*
>(m_task)->value_reference();
258 template <
typename ValueType,
typename Scheduler>
259 class KOKKOS_DEPRECATED BasicFuture {
261 template <
typename,
typename>
262 friend class BasicTaskScheduler;
263 template <
typename,
typename>
264 friend class BasicFuture;
265 friend class Impl::TaskBase;
266 template <
typename,
typename,
typename>
267 friend class Impl::Task;
274 using scheduler_type = Scheduler;
275 using queue_type =
typename scheduler_type::queue_type;
276 using execution_space =
typename scheduler_type::execution_space;
277 using value_type = ValueType;
284 using task_base = Impl::TaskBase;
288 KOKKOS_INLINE_FUNCTION
explicit BasicFuture(task_base* task)
290 if (task) queue_type::assign(&m_task, task);
298 KOKKOS_INLINE_FUNCTION
299 bool is_null()
const {
return nullptr == m_task; }
301 KOKKOS_INLINE_FUNCTION
302 int reference_count()
const {
303 return nullptr != m_task ? m_task->reference_count() : 0;
308 KOKKOS_INLINE_FUNCTION
310 if (m_task) queue_type::assign(&m_task,
nullptr);
315 KOKKOS_INLINE_FUNCTION
316 ~BasicFuture() { clear(); }
320 KOKKOS_INLINE_FUNCTION
321 BasicFuture() noexcept : m_task(
nullptr) {}
323 KOKKOS_INLINE_FUNCTION
324 BasicFuture(BasicFuture&& rhs) noexcept : m_task(rhs.m_task) {
325 rhs.m_task =
nullptr;
328 KOKKOS_INLINE_FUNCTION
329 BasicFuture(
const BasicFuture& rhs) : m_task(nullptr) {
330 if (rhs.m_task) queue_type::assign(&m_task, rhs.m_task);
333 KOKKOS_INLINE_FUNCTION
334 BasicFuture& operator=(BasicFuture&& rhs) noexcept {
337 rhs.m_task =
nullptr;
341 KOKKOS_INLINE_FUNCTION
342 BasicFuture& operator=(BasicFuture
const& rhs) {
343 if (m_task || rhs.m_task) queue_type::assign(&m_task, rhs.m_task);
349 template <
class T,
class S>
350 KOKKOS_INLINE_FUNCTION BasicFuture(
351 BasicFuture<T, S>&& rhs) noexcept
352 : m_task(rhs.m_task) {
353 static_assert(std::is_void<scheduler_type>::value ||
354 std::is_same<scheduler_type, S>::value,
355 "Assigned Futures must have the same scheduler");
358 std::is_void<value_type>::value || std::is_same<value_type, T>::value,
359 "Assigned Futures must have the same value_type");
364 template <
class T,
class S>
365 KOKKOS_INLINE_FUNCTION BasicFuture(
366 BasicFuture<T, S>
const& rhs)
368 static_assert(std::is_void<scheduler_type>::value ||
369 std::is_same<scheduler_type, S>::value,
370 "Assigned Futures must have the same scheduler");
373 std::is_void<value_type>::value || std::is_same<value_type, T>::value,
374 "Assigned Futures must have the same value_type");
376 if (rhs.m_task) queue_type::assign(&m_task, rhs.m_task);
379 template <
class T,
class S>
380 KOKKOS_INLINE_FUNCTION BasicFuture& operator=(BasicFuture<T, S>
const& rhs) {
381 static_assert(std::is_void<scheduler_type>::value ||
382 std::is_same<scheduler_type, S>::value,
383 "Assigned Futures must have the same scheduler");
386 std::is_void<value_type>::value || std::is_same<value_type, T>::value,
387 "Assigned Futures must have the same value_type");
389 if (m_task || rhs.m_task) queue_type::assign(&m_task, rhs.m_task);
393 template <
class T,
class S>
394 KOKKOS_INLINE_FUNCTION BasicFuture& operator=(BasicFuture<T, S>&& rhs) {
395 static_assert(std::is_void<scheduler_type>::value ||
396 std::is_same<scheduler_type, S>::value,
397 "Assigned Futures must have the same scheduler");
400 std::is_void<value_type>::value || std::is_same<value_type, T>::value,
401 "Assigned Futures must have the same value_type");
411 KOKKOS_INLINE_FUNCTION
412 int is_ready() const noexcept {
413 return (
nullptr == m_task) ||
414 (
reinterpret_cast<task_base*
>(task_base::LockTag) == m_task->m_wait);
417 KOKKOS_INLINE_FUNCTION
418 const typename Impl::TaskResult<ValueType>::reference_type
get()
const {
419 if (
nullptr == m_task) {
420 Kokkos::abort(
"Kokkos:::Future::get ERROR: is_null()");
422 return Impl::TaskResult<ValueType>::get(m_task);
427 template <
typename,
typename ExecSpace =
void>
428 struct KOKKOS_DEPRECATED is_future :
public std::false_type {};
430 template <
typename ValueType,
typename Scheduler,
typename ExecSpace>
431 struct KOKKOS_DEPRECATED is_future<BasicFuture<ValueType, Scheduler>, ExecSpace>
432 : std::bool_constant<
433 std::is_same_v<ExecSpace, typename Scheduler::execution_space> ||
434 std::is_void_v<ExecSpace>> {};
442 template <
class Arg1,
class Arg2>
443 class ResolveFutureArgOrder {
445 enum { Arg1_is_space = Kokkos::is_space<Arg1>::value };
446 enum { Arg2_is_space = Kokkos::is_space<Arg2>::value };
447 enum { Arg1_is_value = !Arg1_is_space && !std::is_void_v<Arg1> };
448 enum { Arg2_is_value = !Arg2_is_space && !std::is_void_v<Arg2> };
450 static_assert(!(Arg1_is_space && Arg2_is_space),
451 "Future cannot be given two spaces");
453 static_assert(!(Arg1_is_value && Arg2_is_value),
454 "Future cannot be given two value types");
457 std::conditional_t<Arg1_is_value, Arg1,
458 std::conditional_t<Arg2_is_value, Arg2, void>>;
460 using execution_space =
typename std::conditional_t<
462 std::conditional_t<Arg2_is_space, Arg2, void>>::execution_space;
465 using type = BasicFuture<value_type, TaskScheduler<execution_space>>;
477 template <
class Arg1 =
void,
class Arg2 =
void>
478 using Future KOKKOS_DEPRECATED =
479 typename Impl::ResolveFutureArgOrder<Arg1, Arg2>::type;
483 #ifdef KOKKOS_ENABLE_DEPRECATION_WARNINGS
484 KOKKOS_IMPL_DISABLE_DEPRECATED_WARNINGS_POP()
bool is_null(const boost::shared_ptr< T > &p)