1//
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions
4// are met:
5// * Redistributions of source code must retain the above copyright
6// notice, this list of conditions and the following disclaimer.
7// * Redistributions in binary form must reproduce the above copyright
8// notice, this list of conditions and the following disclaimer in the
9// documentation and/or other materials provided with the distribution.
10// * Neither the name of NVIDIA CORPORATION nor the names of its
11// contributors may be used to endorse or promote products derived
12// from this software without specific prior written permission.
13//
14// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
15// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
18// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26// Copyright (c) 2008-2021 NVIDIA Corporation. All rights reserved.
27
28#ifndef PXTASK_PXTASK_H
29#define PXTASK_PXTASK_H
30
31#include "task/PxTaskDefine.h"
32#include "task/PxTaskManager.h"
33#include "task/PxCpuDispatcher.h"
34#include "foundation/PxAssert.h"
35
36namespace physx
37{
38
39/**
40 * \brief Base class of all task types
41 *
42 * PxBaseTask defines a runnable reference counted task with built-in profiling.
43 */
44class PxBaseTask
45{
46public:
47 PxBaseTask() : mContextID(0), mTm(NULL) {}
48 virtual ~PxBaseTask() {}
49
50 /**
51 * \brief The user-implemented run method where the task's work should be performed
52 *
53 * run() methods must be thread safe, stack friendly (no alloca, etc), and
54 * must never block.
55 */
56 virtual void run() = 0;
57
58 /**
59 * \brief Return a user-provided task name for profiling purposes.
60 *
61 * It does not have to be unique, but unique names are helpful.
62 *
63 * \return The name of this task
64 */
65 virtual const char* getName() const = 0;
66
67 //! \brief Implemented by derived implementation classes
68 virtual void addReference() = 0;
69 //! \brief Implemented by derived implementation classes
70 virtual void removeReference() = 0;
71 //! \brief Implemented by derived implementation classes
72 virtual int32_t getReference() const = 0;
73
74 /** \brief Implemented by derived implementation classes
75 *
76 * A task may assume in its release() method that the task system no longer holds
77 * references to it - so it may safely run its destructor, recycle itself, etc.
78 * provided no additional user references to the task exist
79 */
80 virtual void release() = 0;
81
82 /**
83 * \brief Return PxTaskManager to which this task was submitted
84 *
85 * Note, can return NULL if task was not submitted, or has been
86 * completed.
87 */
88 PX_FORCE_INLINE PxTaskManager* getTaskManager() const
89 {
90 return mTm;
91 }
92
93 PX_FORCE_INLINE void setContextId(PxU64 id) { mContextID = id; }
94 PX_FORCE_INLINE PxU64 getContextId() const { return mContextID; }
95
96protected:
97 PxU64 mContextID; //!< Context ID for profiler interface
98 PxTaskManager* mTm; //!< Owning PxTaskManager instance
99
100 friend class PxTaskMgr;
101};
102
103
104/**
105 * \brief A PxBaseTask implementation with deferred execution and full dependencies
106 *
107 * A PxTask must be submitted to a PxTaskManager to to be executed, Tasks may
108 * optionally be named when they are submitted.
109 */
110class PxTask : public PxBaseTask
111{
112public:
113 PxTask() : mTaskID(0) {}
114 virtual ~PxTask() {}
115
116 //! \brief Release method implementation
117 virtual void release()
118 {
119 PX_ASSERT(mTm);
120
121 // clear mTm before calling taskCompleted() for safety
122 PxTaskManager* save = mTm;
123 mTm = NULL;
124 save->taskCompleted( task&: *this );
125 }
126
127 //! \brief Inform the PxTaskManager this task must finish before the given
128 // task is allowed to start.
129 PX_INLINE void finishBefore( PxTaskID taskID )
130 {
131 PX_ASSERT(mTm);
132 mTm->finishBefore( task&: *this, taskID);
133 }
134
135 //! \brief Inform the PxTaskManager this task cannot start until the given
136 // task has completed.
137 PX_INLINE void startAfter( PxTaskID taskID )
138 {
139 PX_ASSERT(mTm);
140 mTm->startAfter( task&: *this, taskID );
141 }
142
143 /**
144 * \brief Manually increment this task's reference count. The task will
145 * not be allowed to run until removeReference() is called.
146 */
147 PX_INLINE void addReference()
148 {
149 PX_ASSERT(mTm);
150 mTm->addReference( taskID: mTaskID );
151 }
152
153 /**
154 * \brief Manually decrement this task's reference count. If the reference
155 * count reaches zero, the task will be dispatched.
156 */
157 PX_INLINE void removeReference()
158 {
159 PX_ASSERT(mTm);
160 mTm->decrReference( taskID: mTaskID );
161 }
162
163 /**
164 * \brief Return the ref-count for this task
165 */
166 PX_INLINE int32_t getReference() const
167 {
168 return mTm->getReference( taskID: mTaskID );
169 }
170
171 /**
172 * \brief Return the unique ID for this task
173 */
174 PX_INLINE PxTaskID getTaskID() const
175 {
176 return mTaskID;
177 }
178
179 /**
180 * \brief Called by PxTaskManager at submission time for initialization
181 *
182 * Perform simulation step initialization here.
183 */
184 virtual void submitted()
185 {
186 }
187
188protected:
189 PxTaskID mTaskID; //!< ID assigned at submission
190
191 friend class PxTaskMgr;
192};
193
194
195/**
196 * \brief A PxBaseTask implementation with immediate execution and simple dependencies
197 *
198 * A PxLightCpuTask bypasses the PxTaskManager launch dependencies and will be
199 * submitted directly to your scene's CpuDispatcher. When the run() function
200 * completes, it will decrement the reference count of the specified
201 * continuation task.
202 *
203 * You must use a full-blown PxTask if you want your task to be resolved
204 * by another PxTask, or you need more than a single dependency to be
205 * resolved when your task completes, or your task will not run on the
206 * CpuDispatcher.
207 */
208class PxLightCpuTask : public PxBaseTask
209{
210public:
211 PxLightCpuTask()
212 : mCont( NULL )
213 , mRefCount( 0 )
214 {
215 }
216 virtual ~PxLightCpuTask()
217 {
218 mTm = NULL;
219 }
220
221 /**
222 * \brief Initialize this task and specify the task that will have its ref count decremented on completion.
223 *
224 * Submission is deferred until the task's mRefCount is decremented to zero.
225 * Note that we only use the PxTaskManager to query the appropriate dispatcher.
226 *
227 * \param[in] tm The PxTaskManager this task is managed by
228 * \param[in] c The task to be executed when this task has finished running
229 */
230 PX_INLINE void setContinuation(PxTaskManager& tm, PxBaseTask* c)
231 {
232 PX_ASSERT( mRefCount == 0 );
233 mRefCount = 1;
234 mCont = c;
235 mTm = &tm;
236 if( mCont )
237 {
238 mCont->addReference();
239 }
240 }
241
242 /**
243 * \brief Initialize this task and specify the task that will have its ref count decremented on completion.
244 *
245 * This overload of setContinuation() queries the PxTaskManager from the continuation
246 * task, which cannot be NULL.
247 * \param[in] c The task to be executed after this task has finished running
248 */
249 PX_INLINE void setContinuation( PxBaseTask* c )
250 {
251 PX_ASSERT( c );
252 PX_ASSERT( mRefCount == 0 );
253 mRefCount = 1;
254 mCont = c;
255 if( mCont )
256 {
257 mCont->addReference();
258 mTm = mCont->getTaskManager();
259 PX_ASSERT( mTm );
260 }
261 }
262
263 /**
264 * \brief Retrieves continuation task
265 */
266 PX_INLINE PxBaseTask* getContinuation() const
267 {
268 return mCont;
269 }
270
271 /**
272 * \brief Manually decrement this task's reference count. If the reference
273 * count reaches zero, the task will be dispatched.
274 */
275 PX_INLINE void removeReference()
276 {
277 mTm->decrReference(*this);
278 }
279
280 /** \brief Return the ref-count for this task */
281 PX_INLINE int32_t getReference() const
282 {
283 return mRefCount;
284 }
285
286 /**
287 * \brief Manually increment this task's reference count. The task will
288 * not be allowed to run until removeReference() is called.
289 */
290 PX_INLINE void addReference()
291 {
292 mTm->addReference(*this);
293 }
294
295 /**
296 * \brief called by CpuDispatcher after run method has completed
297 *
298 * Decrements the continuation task's reference count, if specified.
299 */
300 PX_INLINE void release()
301 {
302 if( mCont )
303 {
304 mCont->removeReference();
305 }
306 }
307
308protected:
309
310 PxBaseTask* mCont; //!< Continuation task, can be NULL
311 volatile int32_t mRefCount; //!< PxTask is dispatched when reaches 0
312
313 friend class PxTaskMgr;
314};
315
316
317}// end physx namespace
318
319
320#endif // PXTASK_PXTASK_H
321

source code of qtquick3dphysics/src/3rdparty/PhysX/include/task/PxTask.h