include/task/PxTask.h

File members: include/task/PxTask.h

// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//  * Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
//  * Neither the name of NVIDIA CORPORATION nor the names of its
//    contributors may be used to endorse or promote products derived
//    from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2023 NVIDIA Corporation. All rights reserved.

#ifndef PX_TASK_H
#define PX_TASK_H

#include "task/PxTaskManager.h"
#include "task/PxCpuDispatcher.h"
#include "foundation/PxAssert.h"

#if !PX_DOXYGEN
namespace physx
{
#endif

class PxBaseTask
{
public:
    PxBaseTask() : mContextID(0), mTm(NULL) {}
    virtual ~PxBaseTask() {}

    virtual void        run() = 0;

    virtual const char* getName() const = 0;

    virtual void        addReference() = 0;
    virtual void        removeReference() = 0;
    virtual int32_t     getReference() const = 0;

    virtual void        release() = 0;

    PX_FORCE_INLINE PxTaskManager* getTaskManager() const
    {
        return mTm;
    }

    PX_FORCE_INLINE void    setContextId(PxU64 id)          { mContextID = id;      }
    PX_FORCE_INLINE PxU64   getContextId()          const   { return mContextID;    }

protected:
    PxU64               mContextID;
    PxTaskManager*      mTm;

    friend class PxTaskMgr;
};

class PxTask : public PxBaseTask
{
public:
    PxTask() : mTaskID(0) {}
    virtual ~PxTask() {}

    virtual void release() PX_OVERRIDE
    {
        PX_ASSERT(mTm);

        // clear mTm before calling taskCompleted() for safety
        PxTaskManager* save = mTm;
        mTm = NULL;
        save->taskCompleted(*this);
    }

    //         task is allowed to start.
    PX_INLINE void finishBefore(PxTaskID taskID)
    {
        PX_ASSERT(mTm);
        mTm->finishBefore(*this, taskID);
    }

    //         task has completed.
    PX_INLINE void startAfter(PxTaskID taskID)
    {
        PX_ASSERT(mTm);
        mTm->startAfter(*this, taskID);
    }

    virtual void addReference() PX_OVERRIDE
    {
        PX_ASSERT(mTm);
        mTm->addReference(mTaskID);
    }

    virtual void removeReference() PX_OVERRIDE
    {
        PX_ASSERT(mTm);
        mTm->decrReference(mTaskID);
    }

    virtual int32_t getReference() const PX_OVERRIDE
    {
        return mTm->getReference(mTaskID);
    }

    PX_INLINE PxTaskID      getTaskID() const
    {
        return mTaskID;
    }

    virtual void submitted()
    {
    }

protected:
    PxTaskID            mTaskID;

    friend class PxTaskMgr;
};

class PxLightCpuTask : public PxBaseTask
{
public:
    PxLightCpuTask()
        : mCont( NULL )
        , mRefCount( 0 )
    {
    }
    virtual ~PxLightCpuTask()
    {
        mTm = NULL;
    }

    PX_INLINE void setContinuation(PxTaskManager& tm, PxBaseTask* c)
    {
        PX_ASSERT(mRefCount == 0);
        mRefCount = 1;
        mCont = c;
        mTm = &tm;
        if(mCont)
            mCont->addReference();
    }

    PX_INLINE void setContinuation(PxBaseTask* c)
    {
        PX_ASSERT(c);
        PX_ASSERT(mRefCount == 0);
        mRefCount = 1;
        mCont = c;
        if(mCont)
        {
            mCont->addReference();
            mTm = mCont->getTaskManager();
            PX_ASSERT(mTm);
        }
    }

    PX_INLINE PxBaseTask*   getContinuation()   const
    {
        return mCont;
    }

    virtual void removeReference() PX_OVERRIDE
    {
        mTm->decrReference(*this);
    }

    virtual int32_t getReference() const PX_OVERRIDE
    {
        return mRefCount;
    }

    virtual void addReference() PX_OVERRIDE
    {
        mTm->addReference(*this);
    }

    virtual void release() PX_OVERRIDE
    {
        if(mCont)
            mCont->removeReference();
    }

protected:

    PxBaseTask*         mCont;
    volatile int32_t    mRefCount;

    friend class PxTaskMgr;
};

#if !PX_DOXYGEN
} // namespace physx
#endif

#endif