HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_HoudiniExecutionContext.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: UT_HoudiniExecutionContext.h
7  *
8  * COMMENTS:
9  *
10  */
11 
12 #ifndef __UT_HOUDINIEXECUTIONCONTEXT_H__
13 #define __UT_HOUDINIEXECUTIONCONTEXT_H__
14 
15 #include "UT_API.h"
16 #include "UT_BoostAsio.h"
17 #include "UT_Debug.h"
18 #include "UT_IOObject.h"
19 #include "UT_NonCopyable.h"
20 #include "UT_UniquePtr.h"
21 
22 class UT_API UT_HoudiniExecutionContext : public hboost::asio::execution_context
23 {
24 public:
25  class UT_API Event
26  {
27  public:
28  Event() = default;
29  virtual ~Event() = default;
31  virtual void invoke() = 0;
32  };
33 private:
34  template <typename F>
35  class CallbackEvent : public UT_HoudiniExecutionContext::Event
36  {
37  public:
38  CallbackEvent(F f) :
39  myFunc(std::move(f))
40  {}
41 
42  void invoke() override { myFunc(); }
43 
44  private:
45  F myFunc;
46  };
47 public:
48 
50  UT_HoudiniExecutionContext& operator=(const UT_HoudiniExecutionContext&) = delete;
51 
52  // Get the executor used by houdini to post work to the event loop
53  static hboost::asio::executor houdiniExecutor()
54  {
55  return instance()->get_executor();
56  }
57 
59  {
60  UT_ASSERT(theInstance);
61  return theInstance;
62  }
63 
64  static bool hasInstance()
65  {
66  return theInstance != nullptr;
67  }
68 
69  template <typename F>
70  void post(F f)
71  {
72  post_(UTmakeUnique<CallbackEvent<F>>(std::move(f)));
73  }
74 
75 protected:
77  {
78  UT_ASSERT_P(theInstance == nullptr);
79  theInstance = this;
80  }
81  virtual ~UT_HoudiniExecutionContext() = default;
82 
83  virtual hboost::asio::executor get_executor();
84 
85  virtual void post_(UT_UniquePtr<Event> ev) = 0;
86 
87  /// Used ONLY for unit tests where each test should have their own ctx
88  /// so we need to clear the instance.
89  static void clearInstance()
90  {
91  theInstance = nullptr;
92  }
93 
94 private:
95  static UT_HoudiniExecutionContext* theInstance;
96 };
97 
98 // This is an event loop for running just callback events from an exection
99 // context. This is meant to be used when an app doesnt have an event loop but
100 // requires one (i.e. asyncio). This IS NOT houdini event loop.
102 {
103 public:
105  using exception_handler_t = bool(*)(std::exception_ptr);
106 
108  myIOContext(1),
109  myIsRunning(false),
110  myClosed(false)
111  {}
112 
114  {
115  hboost::asio::post(myIOContext, [event = std::move(ev)]()
116  {
117  event->invoke();
118  });
119  }
120 
121  void stop()
122  {
124  if (myWork)
125  {
126  myWork->reset();
127  myWork.reset();
128  }
129  }
130  void close();
131  bool isRunning() const { return myIsRunning; }
132  bool isClosed() const { return myClosed; }
133  void run(exception_handler_t exception_handler = nullptr);
134  void restart()
135  {
136  myIOContext.restart();
137  }
138  exint poll() { return myIOContext.poll(); }
139 
140 private:
141  // TODO: replace this with a custom loop that just processes callbacks.
142  // Using UT_IOContext is overkill here.
143  ASIO_IOContext myIOContext;
145  bool myIsRunning;
146  bool myClosed;
147 };
148 
151 {
152 public:
154 
155  UT_HoudiniWorkEventLoop& loop() { return myLoop; }
156 
157 protected:
158  void post_(UT_UniquePtr<Event> ev) override
159  {
160  myLoop.postEvent(std::move(ev));
161  }
162 
163 private:
165 };
166 
167 /// Defines how the completion handler should run. In this all completion
168 /// handlers are handed off to Qt for processing at a later time.
170 {
171 public:
173  : myCtx(std::addressof(context))
174  {
175  }
176 
177  // When using Boost.Asio with the Network TS these functions should be
178  // defined in favour of the other ones. Since we are not using the Network
179  // TS we define the other set of functions instead.
180 #if 0
181  UI_QtExecutionContext& query(hboost::asio::execution::detail::context_t) const
182  {
183  return *myCtx;
184  }
185 
186  static constexpr hboost::asio::execution::blocking_t query(
187  hboost::asio::execution::blocking_t)
188  {
189  return hboost::asio::execution::blocking.never;
190  }
191 
192  static constexpr hboost::asio::exection::relationship_t query(
193  hboost::asio::execution::relationship_t)
194  {
195  return hboost::asio::execution::relationship.fork;
196  }
197 
198  static constexpr hboost::asio::execution::outstanding_work_t query(
199  hboost::asio::execution::outstanding_work_t)
200  {
201  return hboost::asio::execution::outstanding_work.tracked;
202  }
203 
204  template <typename OtherAllocator>
205  static constexpr auto query(
206  hboost::asio::execution::allocator_t<OtherAllocator>)
207  {
208  return std::allocator<void>();
209  }
210 
211  static constexpr auto query(hboost::asio::execution::allocator_t<void>)
212  {
213  return std::allocator<void>();
214  }
215 
216  template <typename F>
217  void execute(F f) const
218  {
219  myCtx->execute(std::move(f));
220  }
221 #else
222  // All required function to be an executor.
223  UT_HoudiniExecutionContext& context() { return *myCtx; }
224  void on_work_started() const {}
225  void on_work_finished() const {}
226  template <typename F, typename OtherAllocator>
227  void dispatch(F f, const OtherAllocator& a) const
228  {
229  execute(std::move(f));
230  }
231  template <typename F, typename OtherAllocator>
232  void post(F f, const OtherAllocator& a) const
233  {
234  execute(std::move(f));
235  }
236  template <typename F, typename OtherAllocator>
237  void defer(F f, const OtherAllocator& a) const
238  {
239  execute(std::move(f));
240  }
241  template <typename F>
242  void execute(F f) const
243  {
244  myCtx->post(std::move(f));
245  }
246 #endif
247 
248  bool operator==(const UT_HoudiniExecutor& rhs) const
249  {
250  return myCtx == rhs.myCtx;
251  }
252  bool operator!=(const UT_HoudiniExecutor& rhs) const { return !(*this == rhs); }
253 
254 private:
256 };
257 
258 // Ensure the UT_HoudiniExecutor satisfies the executor requirements.
260 
261 #endif // __UT_HOUDINIEXECUTIONCONTEXT_H__
262 
GLenum query
Definition: glad.h:2772
static void cancelAll()
void defer(F f, const OtherAllocator &a) const
GLsizei const GLfloat * value
Definition: glcorearb.h:824
UT_HoudiniExecutionContext & context()
int64 exint
Definition: SYS_Types.h:125
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
static hboost::asio::executor houdiniExecutor()
#define UT_API
Definition: UT_API.h:14
void close() override
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
struct _cl_event * event
Definition: glcorearb.h:2961
bool(*)(std::exception_ptr) exception_handler_t
void post_(UT_UniquePtr< Event > ev) override
GLfloat f
Definition: glcorearb.h:1926
bool operator==(const UT_HoudiniExecutor &rhs) const
bool operator!=(const UT_HoudiniExecutor &rhs) const
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
void postEvent(UT_UniquePtr< event_t > ev)
#define UT_NON_COPYABLE(CLASS)
Define deleted copy constructor and assignment operator inside a class.
std::enable_if< !std::is_array< T >::value, UT_UniquePtr< T >>::type UTmakeUnique(REST &&...args)
Definition: UT_UniquePtr.h:52
hboost::asio::io_context ASIO_IOContext
Definition: UT_BoostAsio.h:74
void post(F f, const OtherAllocator &a) const
static UT_HoudiniExecutionContext * instance()
void dispatch(F f, const OtherAllocator &a) const
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
UT_HoudiniExecutor(UT_HoudiniExecutionContext &context)