aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/Common/src/CmTask.h
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/Common/src/CmTask.h
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/Common/src/CmTask.h')
-rw-r--r--PhysX_3.4/Source/Common/src/CmTask.h257
1 files changed, 257 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/Common/src/CmTask.h b/PhysX_3.4/Source/Common/src/CmTask.h
new file mode 100644
index 00000000..84186b59
--- /dev/null
+++ b/PhysX_3.4/Source/Common/src/CmTask.h
@@ -0,0 +1,257 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_COMMON_TASK
+#define PX_PHYSICS_COMMON_TASK
+
+#include "task/PxTask.h"
+#include "CmPhysXCommon.h"
+#include "PsUserAllocated.h"
+#include "PsAtomic.h"
+#include "PsMutex.h"
+#include "PsInlineArray.h"
+#include "PsFPU.h"
+
+namespace physx
+{
+namespace Cm
+{
+ // wrapper around the public PxLightCpuTask
+ // internal SDK tasks should be inherited from
+ // this and override the runInternal() method
+ // to ensure that the correct floating point
+ // state is set / reset during execution
+ class Task : public physx::PxLightCpuTask
+ {
+ public:
+
+ virtual void run()
+ {
+ PX_SIMD_GUARD;
+ runInternal();
+ }
+
+ virtual void runInternal()=0;
+ };
+
+ // same as Cm::Task but inheriting from physx::PxBaseTask
+ // instead of PxLightCpuTask
+ class BaseTask : public physx::PxBaseTask
+ {
+ public:
+
+ virtual void run()
+ {
+ PX_SIMD_GUARD;
+ runInternal();
+ }
+
+ virtual void runInternal()=0;
+ };
+
+ template <class T, void (T::*Fn)(physx::PxBaseTask*) >
+ class DelegateTask : public Cm::Task, public shdfnd::UserAllocated
+ {
+ public:
+
+ DelegateTask(T* obj, const char* name) :
+ mObj(obj), mName(name) { }
+
+ virtual void runInternal()
+ {
+ (mObj->*Fn)(mCont);
+ }
+
+ virtual const char* getName() const
+ {
+ return mName;
+ }
+
+ void setObject(T* obj) { mObj = obj; }
+
+ private:
+ T* mObj;
+ const char* mName;
+ };
+
+
+ /**
+ \brief A task that maintains a list of dependent tasks.
+
+ This task maintains a list of dependent tasks that have their reference counts
+ reduced on completion of the task.
+
+ The refcount is incremented every time a dependent task is added.
+ */
+ class FanoutTask : public Cm::BaseTask
+ {
+ PX_NOCOPY(FanoutTask)
+ public:
+ FanoutTask(const char* name) : Cm::BaseTask(), mRefCount(0), mName(name), mNotifySubmission(false) {}
+
+ virtual void runInternal() {}
+
+ virtual const char* getName() const { return mName; }
+
+ /**
+ Swap mDependents with mReferencesToRemove when refcount goes to 0.
+ */
+ virtual void removeReference()
+ {
+ shdfnd::Mutex::ScopedLock lock(mMutex);
+ if (!physx::shdfnd::atomicDecrement(&mRefCount))
+ {
+ // prevents access to mReferencesToRemove until release
+ physx::shdfnd::atomicIncrement(&mRefCount);
+ mNotifySubmission = false;
+ PX_ASSERT(mReferencesToRemove.empty());
+ for (PxU32 i = 0; i < mDependents.size(); i++)
+ mReferencesToRemove.pushBack(mDependents[i]);
+ mDependents.clear();
+ mTm->getCpuDispatcher()->submitTask(*this);
+ }
+ }
+
+ /**
+ \brief Increases reference count
+ */
+ virtual void addReference()
+ {
+ shdfnd::Mutex::ScopedLock lock(mMutex);
+ physx::shdfnd::atomicIncrement(&mRefCount);
+ mNotifySubmission = true;
+ }
+
+ /**
+ \brief Return the ref-count for this task
+ */
+ PX_INLINE PxI32 getReference() const
+ {
+ return mRefCount;
+ }
+
+ /**
+ Sets the task manager. Doesn't increase the reference count.
+ */
+ PX_INLINE void setTaskManager(physx::PxTaskManager& tm)
+ {
+ mTm = &tm;
+ }
+
+ /**
+ Adds a dependent task. It also sets the task manager querying it from the dependent task.
+ The refcount is incremented every time a dependent task is added.
+ */
+ PX_INLINE void addDependent(physx::PxBaseTask& dependent)
+ {
+ shdfnd::Mutex::ScopedLock lock(mMutex);
+ physx::shdfnd::atomicIncrement(&mRefCount);
+ mTm = dependent.getTaskManager();
+ mDependents.pushBack(&dependent);
+ dependent.addReference();
+ mNotifySubmission = true;
+ }
+
+ /**
+ Reduces reference counts of the continuation task and the dependent tasks, also
+ clearing the copy of continuation and dependents task list.
+ */
+ virtual void release()
+ {
+ Ps::InlineArray<physx::PxBaseTask*, 10> referencesToRemove;
+
+ {
+ shdfnd::Mutex::ScopedLock lock(mMutex);
+
+ const PxU32 contCount = mReferencesToRemove.size();
+ referencesToRemove.reserve(contCount);
+ for (PxU32 i=0; i < contCount; ++i)
+ referencesToRemove.pushBack(mReferencesToRemove[i]);
+
+ mReferencesToRemove.clear();
+ // allow access to mReferencesToRemove again
+ if (mNotifySubmission)
+ {
+ removeReference();
+ }
+ else
+ {
+ physx::shdfnd::atomicDecrement(&mRefCount);
+ }
+
+ // the scoped lock needs to get freed before the continuation tasks get (potentially) submitted because
+ // those continuation tasks might trigger events that delete this task and corrupt the memory of the
+ // mutex (for example, assume this task is a member of the scene then the submitted tasks cause the simulation
+ // to finish and then the scene gets released which in turn will delete this task. When this task then finally
+ // continues the heap memory will be corrupted.
+ }
+
+ for (PxU32 i=0; i < referencesToRemove.size(); ++i)
+ referencesToRemove[i]->removeReference();
+ }
+
+ protected:
+ volatile PxI32 mRefCount;
+ const char* mName;
+ Ps::InlineArray<physx::PxBaseTask*, 4> mDependents;
+ Ps::InlineArray<physx::PxBaseTask*, 4> mReferencesToRemove;
+ bool mNotifySubmission;
+ Ps::Mutex mMutex; // guarding mDependents and mNotifySubmission
+ };
+
+
+ /**
+ \brief Specialization of FanoutTask class in order to provide the delegation mechanism.
+ */
+ template <class T, void (T::*Fn)(physx::PxBaseTask*) >
+ class DelegateFanoutTask : public FanoutTask, public shdfnd::UserAllocated
+ {
+ public:
+
+ DelegateFanoutTask(T* obj, const char* name) :
+ FanoutTask(name), mObj(obj) { }
+
+ virtual void runInternal()
+ {
+ physx::PxBaseTask* continuation = mReferencesToRemove.empty() ? NULL : mReferencesToRemove[0];
+ (mObj->*Fn)(continuation);
+ }
+
+ void setObject(T* obj) { mObj = obj; }
+
+ private:
+ T* mObj;
+ };
+
+} // namespace Cm
+
+}
+
+#endif