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)) {
 
  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)