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