include/foundation/PxThread.h
File members: include/foundation/PxThread.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-2024 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_THREAD_H
#define PX_THREAD_H
#include "foundation/PxUserAllocated.h"
// todo: these need to go somewhere else
// PT: looks like this is still used on some platforms
#if PX_WINDOWS_FAMILY
#define PxSpinLockPause() __asm pause
#elif PX_LINUX || PX_APPLE_FAMILY || PX_SWITCH
#define PxSpinLockPause() asm("nop")
#else
#error "Platform not supported!"
#endif
#if !PX_DOXYGEN
namespace physx
{
#endif
struct PxThreadPriority
{
enum Enum
{
eHIGH = 0,
eABOVE_NORMAL = 1,
eNORMAL = 2,
eBELOW_NORMAL = 3,
eLOW = 4,
eFORCE_DWORD = 0xffFFffFF
};
};
class PxRunnable
{
public:
PxRunnable() {}
virtual ~PxRunnable() {}
virtual void execute() {}
};
class PX_FOUNDATION_API PxThreadImpl
{
public:
typedef size_t Id; // space for a pointer or an integer
typedef void* (*ExecuteFn)(void*);
static PxU32 getDefaultStackSize();
static Id getId();
PxThreadImpl();
PxThreadImpl(ExecuteFn fn, void* arg, const char* name);
~PxThreadImpl();
void start(PxU32 stackSize, PxRunnable* r);
void kill();
void signalQuit();
bool waitForQuit();
bool quitIsSignalled();
void quit();
PxU32 setAffinityMask(PxU32 mask);
static PxThreadPriority::Enum getPriority(Id threadId);
void setPriority(PxThreadPriority::Enum prio);
void setName(const char* name);
static void sleep(PxU32 ms);
static void yield();
static void yieldProcessor();
static PxU32 getNbPhysicalCores();
static PxU32 getSize();
};
template <typename Alloc = PxReflectionAllocator<PxThreadImpl> >
class PxThreadT : protected Alloc, public PxUserAllocated, public PxRunnable
{
public:
typedef PxThreadImpl::Id Id; // space for a pointer or an integer
PxThreadT(const Alloc& alloc = Alloc()) : Alloc(alloc)
{
mImpl = reinterpret_cast<PxThreadImpl*>(Alloc::allocate(PxThreadImpl::getSize(), PX_FL));
PX_PLACEMENT_NEW(mImpl, PxThreadImpl)();
}
PxThreadT(PxThreadImpl::ExecuteFn fn, void* arg, const char* name, const Alloc& alloc = Alloc()) : Alloc(alloc)
{
mImpl = reinterpret_cast<PxThreadImpl*>(Alloc::allocate(PxThreadImpl::getSize(), PX_FL));
PX_PLACEMENT_NEW(mImpl, PxThreadImpl)(fn, arg, name);
}
virtual ~PxThreadT()
{
mImpl->~PxThreadImpl();
Alloc::deallocate(mImpl);
}
void start(PxU32 stackSize = PxThreadImpl::getDefaultStackSize())
{
mImpl->start(stackSize, this);
}
void kill()
{
mImpl->kill();
}
virtual void execute(void)
{
}
void signalQuit()
{
mImpl->signalQuit();
}
bool waitForQuit()
{
return mImpl->waitForQuit();
}
bool quitIsSignalled()
{
return mImpl->quitIsSignalled();
}
void quit()
{
mImpl->quit();
}
PxU32 setAffinityMask(PxU32 mask)
{
return mImpl->setAffinityMask(mask);
}
static PxThreadPriority::Enum getPriority(PxThreadImpl::Id threadId)
{
return PxThreadImpl::getPriority(threadId);
}
void setPriority(PxThreadPriority::Enum prio)
{
mImpl->setPriority(prio);
}
void setName(const char* name)
{
mImpl->setName(name);
}
static void sleep(PxU32 ms)
{
PxThreadImpl::sleep(ms);
}
static void yield()
{
PxThreadImpl::yield();
}
static void yieldProcesor()
{
PxThreadImpl::yieldProcessor();
}
static PxU32 getDefaultStackSize()
{
return PxThreadImpl::getDefaultStackSize();
}
static PxThreadImpl::Id getId()
{
return PxThreadImpl::getId();
}
static PxU32 getNbPhysicalCores()
{
return PxThreadImpl::getNbPhysicalCores();
}
private:
class PxThreadImpl* mImpl;
};
typedef PxThreadT<> PxThread;
PX_FOUNDATION_API PxU32 PxTlsAlloc();
PX_FOUNDATION_API void PxTlsFree(PxU32 index);
PX_FOUNDATION_API void* PxTlsGet(PxU32 index);
PX_FOUNDATION_API size_t PxTlsGetValue(PxU32 index);
PX_FOUNDATION_API PxU32 PxTlsSet(PxU32 index, void* value);
PX_FOUNDATION_API PxU32 PxTlsSetValue(PxU32 index, size_t value);
#if !PX_DOXYGEN
} // namespace physx
#endif
#endif