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  m_track = rhs.m_track;
216  m_queue = rhs.m_queue;
217  return *this;
218  }
219 
220  explicit BasicTaskScheduler(memory_pool const& arg_memory_pool) noexcept
221  : m_track(), m_queue(nullptr) {
222  using record_type =
223  Kokkos::Impl::SharedAllocationRecord<memory_space,
224  typename queue_type::Destroy>;
225 
226  record_type* record = record_type::allocate(
227  memory_space(), "Kokkos::TaskQueue", sizeof(queue_type));
228 
229  m_queue = new (record->data()) queue_type(arg_memory_pool);
230 
231  record->m_destroy.m_queue = m_queue;
232 
233  m_track.assign_allocated_record_to_uninitialized(record);
234  }
235 
236  BasicTaskScheduler(memory_space const& arg_memory_space,
237  size_t const mempool_capacity,
238  unsigned const mempool_min_block_size // = 1u << 6
239  ,
240  unsigned const mempool_max_block_size // = 1u << 10
241  ,
242  unsigned const mempool_superblock_size // = 1u << 12
243  )
244  : BasicTaskScheduler(memory_pool(
245  arg_memory_space, mempool_capacity, mempool_min_block_size,
246  mempool_max_block_size, mempool_superblock_size)) {}
247 
248  //----------------------------------------
249 
250  KOKKOS_INLINE_FUNCTION
251  queue_type& queue() const noexcept {
252  KOKKOS_EXPECTS(m_queue != nullptr);
253  return *m_queue;
254  }
255 
256  KOKKOS_INLINE_FUNCTION
257  memory_pool* memory() const noexcept {
258  return m_queue ? &(m_queue->m_memory) : (memory_pool*)0;
259  }
260 
261  //----------------------------------------
263  template <typename FunctorType>
264  KOKKOS_FUNCTION size_t spawn_allocation_size() const {
265  return m_queue->template spawn_allocation_size<FunctorType>();
266  }
267 
269  KOKKOS_FUNCTION
270  size_t when_all_allocation_size(int narg) const {
271  return m_queue->when_all_allocation_size(narg);
272  }
273 
274  //----------------------------------------
275 
276  template <int TaskEnum, typename DepFutureType, typename FunctorType>
277  KOKKOS_FUNCTION static Kokkos::BasicFuture<typename FunctorType::value_type,
278  scheduler_type>
279  spawn(Impl::TaskPolicyWithScheduler<TaskEnum, scheduler_type, DepFutureType>&&
280  arg_policy,
281  typename task_base::function_type arg_function,
282  typename task_base::destroy_type arg_destroy,
283  FunctorType&& arg_functor) {
284  return std::move(arg_policy.scheduler())
285  .template _spawn_impl<TaskEnum>(
286  _get_task_ptr(std::move(arg_policy.predecessor())),
287  arg_policy.priority(), arg_function, arg_destroy,
288  std::forward<FunctorType>(arg_functor));
289  }
290 
291  template <int TaskEnum, typename DepFutureType, typename FunctorType>
292  KOKKOS_FUNCTION future_type_for_functor<std::decay_t<FunctorType>> spawn(
293  Impl::TaskPolicyWithPredecessor<TaskEnum, DepFutureType>&& arg_policy,
294  FunctorType&& arg_functor) {
295  using task_type = runnable_task_type<FunctorType>;
296  typename task_type::function_type const ptr = task_type::apply;
297  typename task_type::destroy_type const dtor = task_type::destroy;
298 
299  return _spawn_impl<TaskEnum>(
300  _get_task_ptr(std::move(arg_policy).predecessor()),
301  arg_policy.priority(), ptr, dtor,
302  std::forward<FunctorType>(arg_functor));
303  }
304 
305  template <typename FunctorType, typename ValueType, typename Scheduler>
306  KOKKOS_FUNCTION static void respawn(
307  FunctorType* arg_self,
308  BasicFuture<ValueType, Scheduler> const& arg_dependence,
309  TaskPriority const& arg_priority) {
310  // Precondition: task is in Executing state
311 
312  using value_type = typename FunctorType::value_type;
313  using task_type = Impl::Task<BasicTaskScheduler, value_type, FunctorType>;
314 
315  task_type* const task = static_cast<task_type*>(arg_self);
316 
317  task->m_priority = static_cast<int>(arg_priority);
318 
319  task->add_dependence(arg_dependence.m_task);
320 
321  // Postcondition: task is in Executing-Respawn state
322  }
323 
324  template <typename FunctorType>
325  KOKKOS_FUNCTION static void respawn(FunctorType* arg_self,
326  BasicTaskScheduler const&,
327  TaskPriority const& arg_priority) {
328  // Precondition: task is in Executing state
329 
330  using value_type = typename FunctorType::value_type;
331  using task_type = Impl::Task<BasicTaskScheduler, value_type, FunctorType>;
332 
333  task_type* const task = static_cast<task_type*>(arg_self);
334 
335  task->m_priority = static_cast<int>(arg_priority);
336 
337  task->add_dependence(nullptr);
338 
339  // Postcondition: task is in Executing-Respawn state
340  }
341 
342  //----------------------------------------
346  template <typename ValueType>
347  KOKKOS_FUNCTION BasicFuture<void, scheduler_type> when_all(
348  BasicFuture<ValueType, BasicTaskScheduler> const arg[], int narg) {
349  future_type<void> f;
350 
351  if (narg) {
352  queue_type* q = m_queue;
353 
354  // BasicTaskScheduler const* scheduler_ptr = nullptr;
355 
356  for (int i = 0; i < narg; ++i) {
357  task_base* const t = arg[i].m_task;
358  if (nullptr != t) {
359  // Increment reference count to track subsequent assignment.
360  // This likely has to be SeqCst
361  desul::atomic_inc(&(t->m_ref_count), desul::MemoryOrderSeqCst(),
362  desul::MemoryScopeDevice());
363  if (q != static_cast<queue_type const*>(t->m_queue)) {
364  Kokkos::abort(
365  "Kokkos when_all Futures must be in the same scheduler");
366  }
367  }
368  }
369 
370  if (q != nullptr) { // this should probably handle the queue == 0 case,
371  // but this is deprecated code anyway
372 
373  size_t const alloc_size = q->when_all_allocation_size(narg);
374 
375  f.m_task = reinterpret_cast<task_base*>(q->allocate(alloc_size));
376  // f.m_scheduler = *scheduler_ptr;
377 
378  if (f.m_task) {
379  // Reference count starts at two:
380  // +1 to match decrement when task completes
381  // +1 for the future
382 
383  new (f.m_task) task_base();
384 
385  f.m_task->m_queue = q;
386  f.m_task->m_ref_count = 2;
387  f.m_task->m_alloc_size = static_cast<int32_t>(alloc_size);
388  f.m_task->m_dep_count = narg;
389  f.m_task->m_task_type = task_base::Aggregate;
390 
391  // Assign dependences, reference counts were already incremented
392 
393  task_base* volatile* const dep = f.m_task->aggregate_dependences();
394 
395  for (int i = 0; i < narg; ++i) {
396  dep[i] = arg[i].m_task;
397  }
398 
399  Kokkos::memory_fence();
400 
401  q->schedule_aggregate(f.m_task);
402  // this when_all may be processed at any moment
403  }
404  }
405  }
406 
407  return f;
408  }
409 
410  template <class F>
411  KOKKOS_FUNCTION BasicFuture<void, scheduler_type> when_all(int narg,
412  F const func) {
413  using input_type = decltype(func(0));
414 
415  static_assert(is_future<input_type>::value,
416  "Functor must return a Kokkos::Future");
417 
418  future_type<void> f;
419 
420  if (0 == narg) return f;
421 
422  size_t const alloc_size = m_queue->when_all_allocation_size(narg);
423 
424  f.m_task = reinterpret_cast<task_base*>(m_queue->allocate(alloc_size));
425 
426  if (f.m_task) {
427  // Reference count starts at two:
428  // +1 to match decrement when task completes
429  // +1 for the future
430 
431  new (f.m_task) task_base();
432  // f.m_scheduler = *this;
433 
434  // f.m_task->m_scheduler = &f.m_scheduler;
435  f.m_task->m_queue = m_queue;
436  f.m_task->m_ref_count = 2;
437  f.m_task->m_alloc_size = static_cast<int32_t>(alloc_size);
438  f.m_task->m_dep_count = narg;
439  f.m_task->m_task_type = task_base::Aggregate;
440  // f.m_task->m_apply = nullptr;
441  // f.m_task->m_destroy = nullptr;
442 
443  // Assign dependences, reference counts were already incremented
444 
445  task_base* volatile* const dep = f.m_task->aggregate_dependences();
446 
447  for (int i = 0; i < narg; ++i) {
448  const input_type arg_f = func(i);
449  if (nullptr != arg_f.m_task) {
450  // Not scheduled, so task scheduler is not yet set
451  // if ( m_queue != static_cast< BasicTaskScheduler const * >(
452  // arg_f.m_task->m_scheduler )->m_queue ) {
453  // Kokkos::abort("Kokkos when_all Futures must be in the same
454  // scheduler" );
455  //}
456  // Increment reference count to track subsequent assignment.
457  // This increment likely has to be SeqCst
458  desul::atomic_inc(&(arg_f.m_task->m_ref_count),
459  desul::MemoryOrderSeqCst(),
460  desul::MemoryScopeDevice());
461  dep[i] = arg_f.m_task;
462  }
463  }
464 
465  Kokkos::memory_fence();
466 
467  m_queue->schedule_aggregate(f.m_task);
468  // this when_all may be processed at any moment
469  }
470  return f;
471  }
472 
473  //----------------------------------------
474 
475  KOKKOS_INLINE_FUNCTION
476  int allocation_capacity() const noexcept {
477  return m_queue->m_memory.capacity();
478  }
479 
480  KOKKOS_INLINE_FUNCTION
481  int allocated_task_count() const noexcept { return m_queue->m_count_alloc; }
482 
483  KOKKOS_INLINE_FUNCTION
484  int allocated_task_count_max() const noexcept { return m_queue->m_max_alloc; }
485 
486  KOKKOS_INLINE_FUNCTION
487  long allocated_task_count_accum() const noexcept {
488  return m_queue->m_accum_alloc;
489  }
490 
491  //----------------------------------------
492 
493  template <class S, class Q>
494  friend void wait(Kokkos::BasicTaskScheduler<S, Q> const&);
495 };
496 
497 } // namespace Kokkos
498 
499 //----------------------------------------------------------------------------
500 //----------------------------------------------------------------------------
501 
502 namespace Kokkos {
503 
504 //----------------------------------------------------------------------------
505 // Construct a TaskTeam execution policy
506 
507 template <class T, class Scheduler>
508 KOKKOS_DEPRECATED Impl::TaskPolicyWithPredecessor<
509  Impl::TaskType::TaskTeam, Kokkos::BasicFuture<T, Scheduler>>
510  KOKKOS_INLINE_FUNCTION
511  TaskTeam(Kokkos::BasicFuture<T, Scheduler> arg_future,
512  TaskPriority arg_priority = TaskPriority::Regular) {
513  return {std::move(arg_future), arg_priority};
514 }
515 
516 template <class Scheduler>
517 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<Impl::TaskType::TaskTeam,
518  Scheduler>
519  KOKKOS_INLINE_FUNCTION TaskTeam(
520  Scheduler arg_scheduler,
521  std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value, TaskPriority>
522  arg_priority = TaskPriority::Regular) {
523  return {std::move(arg_scheduler), arg_priority};
524 }
525 
526 template <class Scheduler, class PredecessorFuture>
527 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<
528  Kokkos::Impl::TaskType::TaskTeam, Scheduler, PredecessorFuture>
529  KOKKOS_INLINE_FUNCTION
530  TaskTeam(Scheduler arg_scheduler, PredecessorFuture arg_future,
531  std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value &&
532  Kokkos::is_future<PredecessorFuture>::value,
533  TaskPriority>
534  arg_priority = TaskPriority::Regular) {
535  static_assert(
536  std::is_same_v<typename PredecessorFuture::scheduler_type, Scheduler>,
537  "Can't create a task policy from a scheduler and a future from "
538  "a different scheduler");
539 
540  return {std::move(arg_scheduler), std::move(arg_future), arg_priority};
541 }
542 
543 // Construct a TaskSingle execution policy
544 
545 template <class T, class Scheduler>
546 KOKKOS_DEPRECATED Impl::TaskPolicyWithPredecessor<
547  Impl::TaskType::TaskSingle, Kokkos::BasicFuture<T, Scheduler>>
548  KOKKOS_INLINE_FUNCTION
549  TaskSingle(Kokkos::BasicFuture<T, Scheduler> arg_future,
550  TaskPriority arg_priority = TaskPriority::Regular) {
551  return {std::move(arg_future), arg_priority};
552 }
553 
554 template <class Scheduler>
555 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<Impl::TaskType::TaskSingle,
556  Scheduler>
557  KOKKOS_INLINE_FUNCTION TaskSingle(
558  Scheduler arg_scheduler,
559  std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value, TaskPriority>
560  arg_priority = TaskPriority::Regular) {
561  return {std::move(arg_scheduler), arg_priority};
562 }
563 
564 template <class Scheduler, class PredecessorFuture>
565 KOKKOS_DEPRECATED Impl::TaskPolicyWithScheduler<
566  Kokkos::Impl::TaskType::TaskSingle, Scheduler, PredecessorFuture>
567  KOKKOS_INLINE_FUNCTION
568  TaskSingle(Scheduler arg_scheduler, PredecessorFuture arg_future,
569  std::enable_if_t<Kokkos::is_scheduler<Scheduler>::value &&
570  Kokkos::is_future<PredecessorFuture>::value,
571  TaskPriority>
572  arg_priority = TaskPriority::Regular) {
573  static_assert(
574  std::is_same_v<typename PredecessorFuture::scheduler_type, Scheduler>,
575  "Can't create a task policy from a scheduler and a future from "
576  "a different scheduler");
577 
578  return {std::move(arg_scheduler), std::move(arg_future), arg_priority};
579 }
580 
581 //----------------------------------------------------------------------------
582 
589 template <int TaskEnum, typename Scheduler, typename DepFutureType,
590  typename FunctorType>
591 KOKKOS_DEPRECATED typename Scheduler::template future_type_for_functor<
592  std::decay_t<FunctorType>>
593 host_spawn(Impl::TaskPolicyWithScheduler<TaskEnum, Scheduler, DepFutureType>
594  arg_policy,
595  FunctorType&& arg_functor) {
596  using scheduler_type = Scheduler;
597  using task_type =
598  typename scheduler_type::template runnable_task_type<FunctorType>;
599 
600  static_assert(TaskEnum == Impl::TaskType::TaskTeam ||
601  TaskEnum == Impl::TaskType::TaskSingle,
602  "Kokkos host_spawn requires TaskTeam or TaskSingle");
603 
604  // May be spawning a Cuda task, must use the specialization
605  // to query on-device function pointer.
606  typename task_type::function_type ptr;
607  typename task_type::destroy_type dtor;
608  Kokkos::Impl::TaskQueueSpecialization<
609  scheduler_type>::template get_function_pointer<task_type>(ptr, dtor);
610 
611  return scheduler_type::spawn(std::move(arg_policy), ptr, dtor,
612  std::forward<FunctorType>(arg_functor));
613 }
614 
621 template <int TaskEnum, typename Scheduler, typename DepFutureType,
622  typename FunctorType>
623 KOKKOS_DEPRECATED typename Scheduler::template future_type_for_functor<
624  std::decay_t<FunctorType>>
625  KOKKOS_INLINE_FUNCTION
626  task_spawn(Impl::TaskPolicyWithScheduler<TaskEnum, Scheduler, DepFutureType>
627  arg_policy,
628  FunctorType&& arg_functor) {
629  using scheduler_type = Scheduler;
630 
631  using task_type =
632  typename scheduler_type::template runnable_task_type<FunctorType>;
633 
634  static_assert(TaskEnum == Impl::TaskType::TaskTeam ||
635  TaskEnum == Impl::TaskType::TaskSingle,
636  "Kokkos task_spawn requires TaskTeam or TaskSingle");
637 
638  typename task_type::function_type const ptr = task_type::apply;
639  typename task_type::destroy_type const dtor = task_type::destroy;
640 
641  return scheduler_type::spawn(std::move(arg_policy), ptr, dtor,
642  std::forward<FunctorType>(arg_functor));
643 }
644 
650 template <typename FunctorType, typename T>
651 KOKKOS_DEPRECATED void KOKKOS_INLINE_FUNCTION
652 respawn(FunctorType* arg_self, T const& arg,
653  TaskPriority const& arg_priority = TaskPriority::Regular) {
654  static_assert(Kokkos::is_future<T>::value || Kokkos::is_scheduler<T>::value,
655  "Kokkos respawn argument must be Future or TaskScheduler");
656 
657  T::scheduler_type::respawn(arg_self, arg, arg_priority);
658 }
659 
660 //----------------------------------------------------------------------------
661 
662 // template<typename ValueType, typename Scheduler>
663 // KOKKOS_INLINE_FUNCTION
664 // BasicFuture<void, Scheduler>
665 // when_all(BasicFuture<ValueType, Scheduler> const arg[], int narg)
666 //{
667 // return BasicFuture<void, Scheduler>::scheduler_type::when_all(arg, narg);
668 //}
669 
670 //----------------------------------------------------------------------------
671 // Wait for all runnable tasks to complete
672 
673 template <class ExecSpace, class QueueType>
674 KOKKOS_DEPRECATED inline void wait(
675  BasicTaskScheduler<ExecSpace, QueueType> const& scheduler) {
676  using scheduler_type = BasicTaskScheduler<ExecSpace, QueueType>;
677  scheduler_type::specialization::execute(scheduler);
678  // scheduler.m_queue->execute();
679 }
680 
681 } // namespace Kokkos
682 
683 #ifdef KOKKOS_ENABLE_DEPRECATION_WARNINGS
684 KOKKOS_IMPL_DISABLE_DEPRECATED_WARNINGS_POP()
685 #endif
686 
687 //----------------------------------------------------------------------------
688 //----------------------------------------------------------------------------
689 
691 // END OLD CODE
693 
694 #endif /* #if defined( KOKKOS_ENABLE_TASKDAG ) */
695 #endif /* #ifndef KOKKOS_TASKSCHEDULER_HPP */