Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_TaskScheduler.hpp
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 
17 #include <Kokkos_Macros.hpp>
18 
19 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
20 static_assert(false,
21  "Including non-public Kokkos header files is not allowed.");
22 #endif
23 
24 #ifndef KOKKOS_ENABLE_DEPRECATED_CODE_4
25 #error "The tasking framework is deprecated"
26 #endif
27 
28 #ifndef KOKKOS_TASKSCHEDULER_HPP
29 #define KOKKOS_TASKSCHEDULER_HPP
30 
31 //----------------------------------------------------------------------------
32 
33 #include <Kokkos_Macros.hpp>
34 #if defined(KOKKOS_ENABLE_TASKDAG)
35 
36 #include <Kokkos_Core_fwd.hpp>
37 #include <Kokkos_TaskScheduler_fwd.hpp>
38 //----------------------------------------------------------------------------
39 
40 #include <Kokkos_MemoryPool.hpp>
41 
42 #include <Kokkos_Future.hpp>
43 #include <impl/Kokkos_TaskQueue.hpp>
44 #include <impl/Kokkos_SingleTaskQueue.hpp>
45 #include <impl/Kokkos_TaskQueueMultiple.hpp>
46 #include <impl/Kokkos_TaskPolicyData.hpp>
47 #include <impl/Kokkos_TaskTeamMember.hpp>
48 #include <impl/Kokkos_SimpleTaskScheduler.hpp>
49 
50 //----------------------------------------------------------------------------
51 //----------------------------------------------------------------------------
52 
53 #ifdef KOKKOS_ENABLE_DEPRECATION_WARNINGS
54 // We allow using deprecated classes in this file
55 KOKKOS_IMPL_DISABLE_DEPRECATED_WARNINGS_PUSH()
56 #endif
57 
58 namespace Kokkos {
59 
60 namespace Impl {
61 
62 template <class, class>
63 class TaskExec;
64 
65 } // end namespace Impl
66 
67 template <class ExecSpace, class QueueType>
68 class KOKKOS_DEPRECATED BasicTaskScheduler : public Impl::TaskSchedulerBase {
69  public:
70  using scheduler_type = BasicTaskScheduler;
71  using execution_space = ExecSpace;
72  using queue_type = QueueType;
73  using memory_space = typename queue_type::memory_space;
74  using memory_pool = typename queue_type::memory_pool;
75  using specialization = Impl::TaskQueueSpecialization<BasicTaskScheduler>;
76  using member_type = typename specialization::member_type;
77  using team_scheduler_type = BasicTaskScheduler;
78  template <class Functor>
79  using runnable_task_type =
80  Impl::Task<scheduler_type, typename Functor::value_type, Functor>;
81  template <class ValueType>
82  using future_type = Kokkos::BasicFuture<ValueType, BasicTaskScheduler>;
83  template <class FunctorType>
84  using future_type_for_functor = future_type<typename FunctorType::value_type>;
85 
86  private:
87  using track_type = Kokkos::Impl::SharedAllocationTracker;
88  using task_base = Impl::TaskBase;
89 
90  track_type m_track;
91  queue_type* m_queue;
92 
93  //----------------------------------------
94 
95  template <typename, typename>
96  friend class Impl::TaskQueue;
97  template <typename>
98  friend struct Impl::TaskQueueSpecialization;
99  template <typename, typename>
100  friend class Impl::TaskQueueSpecializationConstrained;
101  template <typename, typename>
102  friend class Impl::TaskTeamMemberAdapter;
103  template <typename, typename>
104  friend class Impl::TaskExec;
105 
106  //----------------------------------------
107 
108  KOKKOS_INLINE_FUNCTION
109  BasicTaskScheduler(track_type arg_track, queue_type* arg_queue)
110  : m_track(std::move(arg_track)), m_queue(std::move(arg_queue)) {}
111 
112  KOKKOS_INLINE_FUNCTION
113  team_scheduler_type get_team_scheduler(int team_rank) const {
114  return {m_track, &m_queue->get_team_queue(team_rank)};
115  }
116 
117  //----------------------------------------
118 
119  KOKKOS_INLINE_FUNCTION
120  static constexpr task_base* _get_task_ptr(std::nullptr_t) { return nullptr; }
121 
122  template <class ValueType>
123  KOKKOS_INLINE_FUNCTION static constexpr task_base* _get_task_ptr(
124  future_type<ValueType>&& f) {
125  return f.m_task;
126  }
127 
128  template <int TaskEnum, typename DepTaskType, typename FunctorType>
129  KOKKOS_FUNCTION
130  Kokkos::BasicFuture<typename FunctorType::value_type, scheduler_type>
131  _spawn_impl(DepTaskType* arg_predecessor_task, TaskPriority arg_priority,
132  typename task_base::function_type arg_function,
133  typename task_base::destroy_type /*arg_destroy*/,
134  FunctorType&& arg_functor) {
135  using functor_future_type =
136  future_type_for_functor<std::decay_t<FunctorType>>;
137  using task_type =
138  Impl::Task<BasicTaskScheduler, typename functor_future_type::value_type,
139  FunctorType>;
140 
141  //----------------------------------------
142  // Give single-thread back-ends an opportunity to clear
143  // queue of ready tasks before allocating a new task
144 
145  // TODO @tasking @optimization DSH re-enable this, maybe?
146  // specialization::iff_single_thread_recursive_execute(scheduler);
147 
148  //----------------------------------------
149 
150  functor_future_type f;
151 
152  // Allocate task from memory pool
153 
154  const size_t alloc_size =
155  m_queue->template spawn_allocation_size<FunctorType>();
156 
157  void* task_storage = m_queue->allocate(alloc_size);
158 
159  if (task_storage) {
160  // Placement new construction
161  // Reference count starts at two:
162  // +1 for the matching decrement when task is complete
163  // +1 for the future
164  f.m_task =
165  new (task_storage) task_type(std::forward<FunctorType>(arg_functor));
166 
167  f.m_task->m_apply = arg_function;
168  // f.m_task->m_destroy = arg_destroy;
169  f.m_task->m_queue = m_queue;
170  f.m_task->m_next = arg_predecessor_task;
171  f.m_task->m_ref_count = 2;
172  f.m_task->m_alloc_size = alloc_size;
173  f.m_task->m_task_type = TaskEnum;
174  f.m_task->m_priority = (int16_t)arg_priority;
175 
176  Kokkos::memory_fence();
177 
178  // The dependence (if any) is processed immediately
179  // within the schedule function, as such the dependence's
180  // reference count does not need to be incremented for
181  // the assignment.
182 
183  m_queue->schedule_runnable(f.m_task);
184  // This task may be updated or executed at any moment,
185  // even during the call to 'schedule'.
186  }
187 
188  return f;
189  }
190 
191  public:
192  KOKKOS_INLINE_FUNCTION
193  BasicTaskScheduler() : m_track(), m_queue(nullptr) {}
194 
195  KOKKOS_INLINE_FUNCTION
196  BasicTaskScheduler(BasicTaskScheduler&& rhs) noexcept
197  : m_track(rhs.m_track), // probably should be a move, but this is
198  // deprecated code anyway
199  m_queue(std::move(rhs.m_queue)) {}
200 
201  KOKKOS_INLINE_FUNCTION
202  BasicTaskScheduler(BasicTaskScheduler const& rhs)
203  : m_track(rhs.m_track), m_queue(rhs.m_queue) {}
204 
205  KOKKOS_INLINE_FUNCTION
206  BasicTaskScheduler& operator=(BasicTaskScheduler&& rhs) noexcept {
207  m_track = rhs.m_track; // probably should be a move, but this is deprecated
208  // code anyway
209  m_queue = std::move(rhs.m_queue);
210  return *this;
211  }
212 
213  KOKKOS_INLINE_FUNCTION
214  BasicTaskScheduler& operator=(BasicTaskScheduler const& rhs) {
215  if (&rhs == this) return *this;
216  m_track = rhs.m_track;
217  m_queue = rhs.m_queue;
218  return *this;
219  }
220 
221  explicit BasicTaskScheduler(memory_pool const& arg_memory_pool) noexcept
222  : m_track(), m_queue(nullptr) {
223  using record_type =
224  Kokkos::Impl::SharedAllocationRecord<memory_space,
225  typename queue_type::Destroy>;
226 
227  record_type* record = record_type::allocate(
228  memory_space(), "Kokkos::TaskQueue", sizeof(queue_type));
229 
230  m_queue = new (record->data()) queue_type(arg_memory_pool);
231 
232  record->m_destroy.m_queue = m_queue;
233 
234  m_track.assign_allocated_record_to_uninitialized(record);
235  }
236 
237  BasicTaskScheduler(memory_space const& arg_memory_space,
238  size_t const mempool_capacity,
239  unsigned const mempool_min_block_size // = 1u << 6
240  ,
241  unsigned const mempool_max_block_size // = 1u << 10
242  ,
243  unsigned const mempool_superblock_size // = 1u << 12
244  )
245  : BasicTaskScheduler(memory_pool(
246  arg_memory_space, mempool_capacity, mempool_min_block_size,
247  mempool_max_block_size, mempool_superblock_size)) {}
248 
249  //----------------------------------------
250 
251  KOKKOS_INLINE_FUNCTION
252  queue_type& queue() const noexcept {
253  KOKKOS_EXPECTS(m_queue != nullptr);
254  return *m_queue;
255  }
256 
257  KOKKOS_INLINE_FUNCTION
258  memory_pool* memory() const noexcept {
259  return m_queue ? &(m_queue->m_memory) : (memory_pool*)0;
260  }
261 
262  //----------------------------------------
264  template <typename FunctorType>
265  KOKKOS_FUNCTION size_t spawn_allocation_size() const {
266  return m_queue->template spawn_allocation_size<FunctorType>();
267  }
268 
270  KOKKOS_FUNCTION
271  size_t when_all_allocation_size(int narg) const {
272  return m_queue->when_all_allocation_size(narg);
273  }
274 
275  //----------------------------------------
276 
277  template <int TaskEnum, typename DepFutureType, typename FunctorType>
278  KOKKOS_FUNCTION static Kokkos::BasicFuture<typename FunctorType::value_type,
279  scheduler_type>
280  spawn(Impl::TaskPolicyWithScheduler<TaskEnum, scheduler_type, DepFutureType>&&
281  arg_policy,
282  typename task_base::function_type arg_function,
283  typename task_base::destroy_type arg_destroy,
284  FunctorType&& arg_functor) {
285  return std::move(arg_policy.scheduler())
286  .template _spawn_impl<TaskEnum>(
287  _get_task_ptr(std::move(arg_policy.predecessor())),
288  arg_policy.priority(), arg_function, arg_destroy,
289  std::forward<FunctorType>(arg_functor));
290  }
291 
292  template <int TaskEnum, typename DepFutureType, typename FunctorType>
293  KOKKOS_FUNCTION future_type_for_functor<std::decay_t<FunctorType>> spawn(
294  Impl::TaskPolicyWithPredecessor<TaskEnum, DepFutureType>&& arg_policy,
295  FunctorType&& arg_functor) {
296  using task_type = runnable_task_type<FunctorType>;
297  typename task_type::function_type const ptr = task_type::apply;
298  typename task_type::destroy_type const dtor = task_type::destroy;
299 
300  auto const priority = arg_policy.priority();
301  return _spawn_impl<TaskEnum>(
302  _get_task_ptr(std::move(arg_policy).predecessor()), priority, ptr, dtor,
303  std::forward<FunctorType>(arg_functor));
304  }
305 
306  template <typename FunctorType, typename ValueType, typename Scheduler>
307  KOKKOS_FUNCTION static void respawn(
308  FunctorType* arg_self,
309  BasicFuture<ValueType, Scheduler> const& arg_dependence,
310  TaskPriority const& arg_priority) {
311  // Precondition: task is in Executing state
312 
313  using value_type = typename FunctorType::value_type;
314  using task_type = Impl::Task<BasicTaskScheduler, value_type, FunctorType>;
315 
316  task_type* const task = static_cast<task_type*>(arg_self);
317 
318  task->m_priority = static_cast<int>(arg_priority);
319 
320  task->add_dependence(arg_dependence.m_task);
321 
322  // Postcondition: task is in Executing-Respawn state
323  }
324 
325  template <typename FunctorType>
326  KOKKOS_FUNCTION static void respawn(FunctorType* arg_self,
327  BasicTaskScheduler const&,
328  TaskPriority const& arg_priority) {
329  // Precondition: task is in Executing state
330 
331  using value_type = typename FunctorType::value_type;
332  using task_type = Impl::Task<BasicTaskScheduler, value_type, FunctorType>;
333 
334  task_type* const task = static_cast<task_type*>(arg_self);
335 
336  task->m_priority = static_cast<int>(arg_priority);
337 
338  task->add_dependence(nullptr);
339 
340  // Postcondition: task is in Executing-Respawn state
341  }
342 
343  //----------------------------------------
347  template <typename ValueType>
348  KOKKOS_FUNCTION BasicFuture<void, scheduler_type> when_all(
349  BasicFuture<ValueType, BasicTaskScheduler> const arg[], int narg) {
350  future_type<void> f;
351 
352  if (narg) {
353  queue_type* q = m_queue;
354 
355  // BasicTaskScheduler const* scheduler_ptr = nullptr;
356 
357  for (int i = 0; i < narg; ++i) {
358  task_base* const t = arg[i].m_task;
359  if (nullptr != t) {
360  // Increment reference count to track subsequent assignment.
361  // This likely has to be SeqCst
362  desul::atomic_inc(&(t->m_ref_count), desul::MemoryOrderSeqCst(),
363  desul::MemoryScopeDevice());
364  if (q != static_cast<queue_type const*>(t->m_queue)) {
365  Kokkos::abort(
366  "Kokkos when_all Futures must be in the same scheduler");
367  }
368  }
369  }
370 
371  if (q != nullptr) { // this should probably handle the queue == 0 case,
372  // but this is deprecated code anyway
373 
374  size_t const alloc_size = q->when_all_allocation_size(narg);
375 
376  f.m_task = reinterpret_cast<task_base*>(q->allocate(alloc_size));
377  // f.m_scheduler = *scheduler_ptr;
378 
379  if (f.m_task) {
380  // Reference count starts at two:
381  // +1 to match decrement when task completes
382  // +1 for the future
383 
384  new (f.m_task) task_base();
385 
386  f.m_task->m_queue = q;
387  f.m_task->m_ref_count = 2;
388  f.m_task->m_alloc_size = static_cast<int32_t>(alloc_size);
389  f.m_task->m_dep_count = narg;
390  f.m_task->m_task_type = task_base::Aggregate;
391 
392  // Assign dependences, reference counts were already incremented
393 
394  task_base* volatile* const dep = f.m_task->aggregate_dependences();
395 
396  for (int i = 0; i < narg; ++i) {
397  dep[i] = arg[i].m_task;
398  }
399 
400  Kokkos::memory_fence();
401 
402  q->schedule_aggregate(f.m_task);
403  // this when_all may be processed at any moment
404  }
405  }
406  }
407 
408  return f;
409  }
410 
411  template <class F>
412  KOKKOS_FUNCTION BasicFuture<void, scheduler_type> when_all(int narg,
413  F const func) {
414  using input_type = decltype(func(0));
415 
416  static_assert(is_future<input_type>::value,
417  "Functor must return a Kokkos::Future");
418 
419  future_type<void> f;
420 
421  if (0 == narg) return f;
422 
423  size_t const alloc_size = m_queue->when_all_allocation_size(narg);
424 
425  f.m_task = reinterpret_cast<task_base*>(m_queue->allocate(alloc_size));
426 
427  if (f.m_task) {
428  // Reference count starts at two:
429  // +1 to match decrement when task completes
430  // +1 for the future
431 
432  new (f.m_task) task_base();
433  // f.m_scheduler = *this;
434 
435  // f.m_task->m_scheduler = &f.m_scheduler;
436  f.m_task->m_queue = m_queue;
437  f.m_task->m_ref_count = 2;
438  f.m_task->m_alloc_size = static_cast<int32_t>(alloc_size);
439  f.m_task->m_dep_count = narg;
440  f.m_task->m_task_type = task_base::Aggregate;
441  // f.m_task->m_apply = nullptr;
442  // f.m_task->m_destroy = nullptr;
443 
444  // Assign dependences, reference counts were already incremented
445 
446  task_base* volatile* const dep = f.m_task->aggregate_dependences();
447 
448  for (int i = 0; i < narg; ++i) {
449  const input_type arg_f = func(i);
450  if (nullptr != arg_f.m_task) {
451  // Not scheduled, so task scheduler is not yet set
452  // if ( m_queue != static_cast< BasicTaskScheduler const * >(
453  // arg_f.m_task->m_scheduler )->m_queue ) {
454  // Kokkos::abort("Kokkos when_all Futures must be in the same
455  // scheduler" );
456  //}
457  // Increment reference count to track subsequent assignment.
458  // This increment likely has to be SeqCst
459  desul::atomic_inc(&(arg_f.m_task->m_ref_count),
460  desul::MemoryOrderSeqCst(),
461  desul::MemoryScopeDevice());
462  dep[i] = arg_f.m_task;
463  }
464  }
465 
466  Kokkos::memory_fence();
467 
468  m_queue->schedule_aggregate(f.m_task);
469  // this when_all may be processed at any moment
470  }
471  return f;
472  }
473 
474  //----------------------------------------
475 
476  KOKKOS_INLINE_FUNCTION
477  int allocation_capacity() const noexcept {
478  return m_queue->m_memory.capacity();
479  }
480 
481  KOKKOS_INLINE_FUNCTION
482  int allocated_task_count() const noexcept { return m_queue->m_count_alloc; }
483 
484  KOKKOS_INLINE_FUNCTION
485  int allocated_task_count_max() const noexcept { return m_queue->m_max_alloc; }
486 
487  KOKKOS_INLINE_FUNCTION
488  long allocated_task_count_accum() const noexcept {
489  return m_queue->m_accum_alloc;
490  }
491 
492  //----------------------------------------
493 
494  template <class S, class Q>
495  friend void wait(Kokkos::BasicTaskScheduler<S, Q> const&);
496 };
497 
498 } // namespace Kokkos
499 
500 //----------------------------------------------------------------------------
501 //----------------------------------------------------------------------------
502 
503 namespace Kokkos {
504 
505 //----------------------------------------------------------------------------
506 // Construct a TaskTeam execution policy
507 
508 template <class T, class Scheduler>
509 KOKKOS_DEPRECATED Impl::TaskPolicyWithPredecessor<
510  Impl::TaskType::TaskTeam, Kokkos::BasicFuture<T, Scheduler>>
511  KOKKOS_INLINE_FUNCTION
512  TaskTeam(Kokkos::BasicFuture<T, Scheduler> arg_future,
513  TaskPriority arg_priority = TaskPriority::Regular) {
514  return {std::move(arg_future), arg_priority};
515 }
516 
517 template <class Scheduler>
518 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<Impl::TaskType::TaskTeam,
519  Scheduler>
520  KOKKOS_INLINE_FUNCTION TaskTeam(
521  Scheduler arg_scheduler,
522  std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value, TaskPriority>
523  arg_priority = TaskPriority::Regular) {
524  return {std::move(arg_scheduler), arg_priority};
525 }
526 
527 template <class Scheduler, class PredecessorFuture>
528 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<
529  Kokkos::Impl::TaskType::TaskTeam, Scheduler, PredecessorFuture>
530  KOKKOS_INLINE_FUNCTION
531  TaskTeam(Scheduler arg_scheduler, PredecessorFuture arg_future,
532  std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value &&
533  Kokkos::is_future<PredecessorFuture>::value,
534  TaskPriority>
535  arg_priority = TaskPriority::Regular) {
536  static_assert(
537  std::is_same_v<typename PredecessorFuture::scheduler_type, Scheduler>,
538  "Can't create a task policy from a scheduler and a future from "
539  "a different scheduler");
540 
541  return {std::move(arg_scheduler), std::move(arg_future), arg_priority};
542 }
543 
544 // Construct a TaskSingle execution policy
545 
546 template <class T, class Scheduler>
547 KOKKOS_DEPRECATED Impl::TaskPolicyWithPredecessor<
548  Impl::TaskType::TaskSingle, Kokkos::BasicFuture<T, Scheduler>>
549  KOKKOS_INLINE_FUNCTION
550  TaskSingle(Kokkos::BasicFuture<T, Scheduler> arg_future,
551  TaskPriority arg_priority = TaskPriority::Regular) {
552  return {std::move(arg_future), arg_priority};
553 }
554 
555 template <class Scheduler>
556 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<Impl::TaskType::TaskSingle,
557  Scheduler>
558  KOKKOS_INLINE_FUNCTION TaskSingle(
559  Scheduler arg_scheduler,
560  std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value, TaskPriority>
561  arg_priority = TaskPriority::Regular) {
562  return {std::move(arg_scheduler), arg_priority};
563 }
564 
565 template <class Scheduler, class PredecessorFuture>
566 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<
567  Kokkos::Impl::TaskType::TaskSingle, Scheduler, PredecessorFuture>
568  KOKKOS_INLINE_FUNCTION
569  TaskSingle(Scheduler arg_scheduler, PredecessorFuture arg_future,
570  std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value &&
571  Kokkos::is_future<PredecessorFuture>::value,
572  TaskPriority>
573  arg_priority = TaskPriority::Regular) {
574  static_assert(
575  std::is_same_v<typename PredecessorFuture::scheduler_type, Scheduler>,
576  "Can't create a task policy from a scheduler and a future from "
577  "a different scheduler");
578 
579  return {std::move(arg_scheduler), std::move(arg_future), arg_priority};
580 }
581 
582 //----------------------------------------------------------------------------
583 
590 template <int TaskEnum, typename Scheduler, typename DepFutureType,
591  typename FunctorType>
592 KOKKOS_DEPRECATED typename Scheduler::template future_type_for_functor<
593  std::decay_t<FunctorType>>
594 host_spawn(Impl::TaskPolicyWithScheduler<TaskEnum, Scheduler, DepFutureType>
595  arg_policy,
596  FunctorType&& arg_functor) {
597  using scheduler_type = Scheduler;
598  using task_type =
599  typename scheduler_type::template runnable_task_type<FunctorType>;
600 
601  static_assert(TaskEnum == Impl::TaskType::TaskTeam ||
602  TaskEnum == Impl::TaskType::TaskSingle,
603  "Kokkos host_spawn requires TaskTeam or TaskSingle");
604 
605  // May be spawning a Cuda task, must use the specialization
606  // to query on-device function pointer.
607  typename task_type::function_type ptr;
608  typename task_type::destroy_type dtor;
609  Kokkos::Impl::TaskQueueSpecialization<
610  scheduler_type>::template get_function_pointer<task_type>(ptr, dtor);
611 
612  return scheduler_type::spawn(std::move(arg_policy), ptr, dtor,
613  std::forward<FunctorType>(arg_functor));
614 }
615 
622 template <int TaskEnum, typename Scheduler, typename DepFutureType,
623  typename FunctorType>
624 KOKKOS_DEPRECATED typename Scheduler::template future_type_for_functor<
625  std::decay_t<FunctorType>>
626  KOKKOS_INLINE_FUNCTION
627  task_spawn(Impl::TaskPolicyWithScheduler<TaskEnum, Scheduler, DepFutureType>
628  arg_policy,
629  FunctorType&& arg_functor) {
630  using scheduler_type = Scheduler;
631 
632  using task_type =
633  typename scheduler_type::template runnable_task_type<FunctorType>;
634 
635  static_assert(TaskEnum == Impl::TaskType::TaskTeam ||
636  TaskEnum == Impl::TaskType::TaskSingle,
637  "Kokkos task_spawn requires TaskTeam or TaskSingle");
638 
639  typename task_type::function_type const ptr = task_type::apply;
640  typename task_type::destroy_type const dtor = task_type::destroy;
641 
642  return scheduler_type::spawn(std::move(arg_policy), ptr, dtor,
643  std::forward<FunctorType>(arg_functor));
644 }
645 
651 template <typename FunctorType, typename T>
652 KOKKOS_DEPRECATED void KOKKOS_INLINE_FUNCTION
653 respawn(FunctorType* arg_self, T const& arg,
654  TaskPriority const& arg_priority = TaskPriority::Regular) {
655  static_assert(Kokkos::is_future<T>::value || Kokkos::is_scheduler<T>::value,
656  "Kokkos respawn argument must be Future or TaskScheduler");
657 
658  T::scheduler_type::respawn(arg_self, arg, arg_priority);
659 }
660 
661 //----------------------------------------------------------------------------
662 
663 // template<typename ValueType, typename Scheduler>
664 // KOKKOS_INLINE_FUNCTION
665 // BasicFuture<void, Scheduler>
666 // when_all(BasicFuture<ValueType, Scheduler> const arg[], int narg)
667 //{
668 // return BasicFuture<void, Scheduler>::scheduler_type::when_all(arg, narg);
669 //}
670 
671 //----------------------------------------------------------------------------
672 // Wait for all runnable tasks to complete
673 
674 template <class ExecSpace, class QueueType>
675 KOKKOS_DEPRECATED inline void wait(
676  BasicTaskScheduler<ExecSpace, QueueType> const& scheduler) {
677  using scheduler_type = BasicTaskScheduler<ExecSpace, QueueType>;
678  scheduler_type::specialization::execute(scheduler);
679  // scheduler.m_queue->execute();
680 }
681 
682 } // namespace Kokkos
683 
684 #ifdef KOKKOS_ENABLE_DEPRECATION_WARNINGS
685 KOKKOS_IMPL_DISABLE_DEPRECATED_WARNINGS_POP()
686 #endif
687 
688 //----------------------------------------------------------------------------
689 //----------------------------------------------------------------------------
690 
692 // END OLD CODE
694 
695 #endif /* #if defined( KOKKOS_ENABLE_TASKDAG ) */
696 #endif /* #ifndef KOKKOS_TASKSCHEDULER_HPP */