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 #include <SYS/SYS_TypeTraits.h>
23 
24 class UT_HoudiniExecutor;
25 
26 class UT_API UT_HoudiniExecutionContext : public hboost::asio::execution_context
27 {
28 public:
29  class UT_API Event
30  {
31  public:
32  Event() = default;
33  virtual ~Event() = default;
35  virtual void invoke() = 0;
36  };
37 private:
38  template <typename F>
39  class CallbackEvent : public UT_HoudiniExecutionContext::Event
40  {
41  public:
42  CallbackEvent(F f) :
43  myFunc(std::move(f))
44  {}
45 
46  void invoke() override { myFunc(); }
47 
48  private:
49  F myFunc;
50  };
51 public:
53 
56 
57  // Get the executor used by houdini to post work to the event loop
58  static UT_HoudiniExecutor houdiniExecutor();
59 
61  {
62  UT_ASSERT(theInstance);
63  return theInstance;
64  }
65 
66  static bool hasInstance()
67  {
68  return theInstance != nullptr;
69  }
70 
71  template <typename F>
72  void post(F f)
73  {
74  post_(UTmakeUnique<CallbackEvent<F>>(std::move(f)));
75  }
76 
77  virtual void onWorkStarted() {}
78  virtual void onWorkFinished() {}
79 
80  UT_HoudiniExecutor get_executor();
81  UT_HoudiniExecutor get_executor() const;
82 
83 protected:
85  {
86  UT_ASSERT_P(theInstance == nullptr);
87  theInstance = this;
88  }
89  virtual ~UT_HoudiniExecutionContext() = default;
90 
91  virtual void post_(UT_UniquePtr<Event> ev) = 0;
92 
93  /// Used ONLY for unit tests where each test should have their own ctx
94  /// so we need to clear the instance.
95  static void clearInstance()
96  {
97  theInstance = nullptr;
98  }
99 
100 private:
101  static UT_HoudiniExecutionContext* theInstance;
102 };
103 
104 // This is an event loop for running just callback events from an exection
105 // context. This is meant to be used when an app doesnt have an event loop but
106 // requires one (i.e. asyncio). This IS NOT houdini event loop.
108 {
109 public:
111  using exception_handler_t = bool(*)(std::exception_ptr);
112 
114  myIOContext(1),
115  myIsRunning(false),
116  myClosed(false)
117  {}
118 
120  {
121  hboost::asio::post(myIOContext, [event = std::move(ev)]()
122  {
123  event->invoke();
124  });
125  }
126 
127  void stop()
128  {
130  if (myWork)
131  {
132  myWork->reset();
133  myWork.reset();
134  }
135  }
136  void close();
137  bool isRunning() const { return myIsRunning; }
138  bool isClosed() const { return myClosed; }
139  void run(exception_handler_t exception_handler = nullptr);
140  void restart()
141  {
142  myIOContext.restart();
143  }
144  exint poll() { return myIOContext.poll(); }
145 
146 private:
147  // TODO: replace this with a custom loop that just processes callbacks.
148  // Using UT_IOContext is overkill here.
149  ASIO_IOContext myIOContext;
151  bool myIsRunning;
152  bool myClosed;
153 };
154 
157 {
158 public:
160 
161  UT_HoudiniWorkEventLoop& loop() { return myLoop; }
162 
163 protected:
164  void post_(UT_UniquePtr<Event> ev) override
165  {
166  myLoop.postEvent(std::move(ev));
167  }
168 
169 private:
171 };
172 
173 /// Defines how the completion handler should run. In this all completion
174 /// handlers are handed off to Qt for processing at a later time.
176 {
177 public:
179  : myCtx(SYSaddressof(context))
180  {
181  }
182 
183  // When using Boost.Asio with the Network TS these functions should be
184  // defined in favour of the other ones. Since we are not using the Network
185  // TS we define the other set of functions instead.
186 #if 0
187  UI_QtExecutionContext& query(hboost::asio::execution::detail::context_t) const
188  {
189  return *myCtx;
190  }
191 
192  static constexpr hboost::asio::execution::blocking_t query(
193  hboost::asio::execution::blocking_t)
194  {
195  return hboost::asio::execution::blocking.never;
196  }
197 
198  static constexpr hboost::asio::exection::relationship_t query(
199  hboost::asio::execution::relationship_t)
200  {
201  return hboost::asio::execution::relationship.fork;
202  }
203 
204  static constexpr hboost::asio::execution::outstanding_work_t query(
205  hboost::asio::execution::outstanding_work_t)
206  {
207  return hboost::asio::execution::outstanding_work.tracked;
208  }
209 
210  template <typename OtherAllocator>
211  static constexpr auto query(
212  hboost::asio::execution::allocator_t<OtherAllocator>)
213  {
214  return std::allocator<void>();
215  }
216 
217  static constexpr auto query(hboost::asio::execution::allocator_t<void>)
218  {
219  return std::allocator<void>();
220  }
221 
222  template <typename F>
223  void execute(F f) const
224  {
225  myCtx->execute(std::move(f));
226  }
227 #else
228  // All required function to be an executor.
229  UT_HoudiniExecutionContext& context() const { return *myCtx; }
230  void on_work_started() const { myCtx->onWorkStarted(); }
231  void on_work_finished() const { myCtx->onWorkFinished(); }
232  template <typename F, typename OtherAllocator>
233  void dispatch(F f, const OtherAllocator& a) const
234  {
235  execute(std::move(f));
236  }
237  template <typename F, typename OtherAllocator>
238  void post(F f, const OtherAllocator& a) const
239  {
240  execute(std::move(f));
241  }
242  template <typename F, typename OtherAllocator>
243  void defer(F f, const OtherAllocator& a) const
244  {
245  execute(std::move(f));
246  }
247  template <typename F>
248  void execute(F f) const
249  {
250  myCtx->post(std::move(f));
251  }
252 #endif
253 
254  bool operator==(const UT_HoudiniExecutor& rhs) const
255  {
256  return myCtx == rhs.myCtx;
257  }
258  bool operator!=(const UT_HoudiniExecutor& rhs) const { return !(*this == rhs); }
259 
260 private:
262 };
263 
264 // Ensure the UT_HoudiniExecutor satisfies the executor requirements.
266 
267 #endif // __UT_HOUDINIEXECUTIONCONTEXT_H__
268 
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
int64 exint
Definition: SYS_Types.h:125
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
#define UT_API
Definition: UT_API.h:14
void close() override
OutGridT const XformOp bool bool
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
SYS_NO_DISCARD_RESULT SYS_FORCE_INLINE constexpr T * SYSaddressof(T &val) noexcept
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.
UT_UniquePtr< T > UTmakeUnique(REST &&...args)
Definition: UT_UniquePtr.h:50
hboost::asio::io_context ASIO_IOContext
Definition: UT_BoostAsio.h:74
void post(F f, const OtherAllocator &a) const
LeafData & operator=(const LeafData &)=delete
static UT_HoudiniExecutionContext * instance()
void dispatch(F f, const OtherAllocator &a) const
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
UT_HoudiniExecutionContext & context() const
UT_HoudiniExecutor(UT_HoudiniExecutionContext &context)
int invoke(const Func &taskFunc1, Rest...taskFuncN)
Definition: Invoke.h:64