MeVisLab Toolbox Reference
mlTaskSystem.h
Go to the documentation of this file.
1 /*************************************************************************************
2 **
3 ** Copyright 2022, MeVis Medical Solutions AG
4 **
5 ** The user may use this file in accordance with the license agreement provided with
6 ** the Software or, alternatively, in accordance with the terms contained in a
7 ** written agreement between the user and MeVis Medical Solutions AG.
8 **
9 ** For further information use the contact form at https://www.mevislab.de/contact
10 **
11 **************************************************************************************/
12 
13 #pragma once
14 
15 #include "mlUtilsSystem.h"
16 
17 #include <stlab/concurrency/task.hpp>
18 #include <stlab/concurrency/future.hpp>
19 #include <stlab/concurrency/immediate_executor.hpp>
20 #include <stlab/concurrency/await.hpp>
21 
22 ML_START_NAMESPACE
23 
24 void ML_UTILS_EXPORT execute_low(stlab::task<void()> f);
25 void ML_UTILS_EXPORT execute_default(stlab::task<void()> f);
26 void ML_UTILS_EXPORT execute_high(stlab::task<void()> f);
27 
28 namespace detail
29 {
30  template <void (*Execute)(stlab::task<void()>)>
31  struct executor
32  {
33  void operator()(stlab::task<void()> f) const
34  {
35  Execute(std::move(f));
36  }
37  };
38 
39 #if STLAB_TASK_SYSTEM(PORTABLE)
40  ML_UTILS_EXPORT stlab::detail::priority_task_system& pts();
41 #endif
42 }
43 
44 /*
45  * These type definitions provide an interface to the stlab's
46  * TaskSystem. Use only instances of these types to access
47  * it.
48  *
49  * Never use the stlab::default_executor directly because
50  * that would instantiate in each shared library and in main
51  * a separate instance of the TaskSystem. This is against the
52  * principles that there should only be one task system per
53  * application and destruction of the TaskSystem while closing
54  * the applications does not work as intended.
55  */
59 
60 /*
61  * This function must be called just before the end of
62  * int main(). It ensures that all remaining tasks which
63  * are still in the queue of the TaskSystem will not executed
64  * any more and that the TaskSystem is shutdown in a controlled
65  * manner.
66  */
68 
69 
70 namespace taskSystem
71 {
72  /*
73  * This is a copy of stlab::await, which ensures that always the same instance of the
74  * priority_task_system singleton is returned (via detail::pts()), regardless of the compilation unit.
75  * See https://github.com/stlab/libraries/issues/519
76  */
77  template <typename T>
78  T await(stlab::future<T> x) {
79  if (auto result = x.get_try())
80  return stlab::detail::_get_optional<decltype(result)>{}(std::move(result)); // if ready, done
81 
82  std::mutex m;
83  std::condition_variable condition;
84  bool flag{false};
85 
86  auto hold = std::move(x).recover(stlab::immediate_executor, [&](auto&& r) {
87  x = std::forward<decltype(r)>(r);
88  {
89  std::unique_lock<std::mutex> lock{m};
90  flag = true;
91  condition.notify_one(); // must notify under lock
92  }
93  });
94 
95  #if STLAB_TASK_SYSTEM(PORTABLE)
96  if (!detail::pts().wake()) detail::pts().add_thread();
97 
98  /*
99  If no tasks are available we wait for one tick of the system clock and exponentially
100  back off on the wait as long as no tasks are available.
101  */
102 
103  for (auto backoff{std::chrono::steady_clock::duration{std::chrono::milliseconds{1}}}; true;
104  backoff *= 2) {
105  {
106  std::unique_lock<std::mutex> lock{m};
107  if (condition.wait_for(lock, backoff, [&] { return flag; })) {
108  break;
109  }
110  }
111  detail::pts().wake(); // try to wake something to unstick.
112  }
113 
114  #else
115 
116  {
117  std::unique_lock<std::mutex> lock{m};
118  condition.wait(lock, [&] { return flag; });
119  }
120 
121  #endif
122 
123  return stlab::detail::_get_ready_future<T>{}(std::move(x));
124  }
125 }
126 
127 ML_END_NAMESPACE
@ T
Definition: SoKeyGrabber.h:71
#define ML_UTILS_EXPORT
Defines platform dependent DLL export macro for mlUtils.
Definition: mlUtilities.h:20
T await(stlab::future< T > x)
Definition: mlTaskSystem.h:78
void ML_UTILS_EXPORT execute_high(stlab::task< void()> f)
void ML_UTILS_EXPORT execute_low(stlab::task< void()> f)
void ML_UTILS_EXPORT pre_exit()
void ML_UTILS_EXPORT execute_default(stlab::task< void()> f)
void operator()(stlab::task< void()> f) const
Definition: mlTaskSystem.h:33