Add and use an intrusive_ptr type
This commit is contained in:
+5
-58
@@ -906,53 +906,7 @@ constexpr ALCint alcEFXMinorVersion = 0;
|
||||
al::FlexArray<ALCcontext*> EmptyContextArray{0u};
|
||||
|
||||
|
||||
/* Simple RAII device reference. Takes the reference of the provided ALCdevice,
|
||||
* and decrements it when leaving scope. Movable (transfer reference) but not
|
||||
* copyable (no new references).
|
||||
*/
|
||||
class DeviceRef {
|
||||
ALCdevice *mDev{nullptr};
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
if(mDev)
|
||||
mDev->release();
|
||||
mDev = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
DeviceRef() noexcept = default;
|
||||
DeviceRef(DeviceRef&& rhs) noexcept : mDev{rhs.mDev}
|
||||
{ rhs.mDev = nullptr; }
|
||||
explicit DeviceRef(ALCdevice *dev) noexcept : mDev(dev) { }
|
||||
~DeviceRef() { reset(); }
|
||||
|
||||
DeviceRef& operator=(const DeviceRef&) = delete;
|
||||
DeviceRef& operator=(DeviceRef&& rhs) noexcept
|
||||
{
|
||||
std::swap(mDev, rhs.mDev);
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool() const noexcept { return mDev != nullptr; }
|
||||
|
||||
ALCdevice* operator->() const noexcept { return mDev; }
|
||||
ALCdevice* get() const noexcept { return mDev; }
|
||||
|
||||
ALCdevice* release() noexcept
|
||||
{
|
||||
ALCdevice *ret{mDev};
|
||||
mDev = nullptr;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator==(const DeviceRef &lhs, const ALCdevice *rhs) noexcept
|
||||
{ return lhs.get() == rhs; }
|
||||
inline bool operator!=(const DeviceRef &lhs, const ALCdevice *rhs) noexcept
|
||||
{ return !(lhs == rhs); }
|
||||
inline bool operator<(const DeviceRef &lhs, const ALCdevice *rhs) noexcept
|
||||
{ return lhs.get() < rhs; }
|
||||
using DeviceRef = al::intrusive_ptr<ALCdevice>;
|
||||
|
||||
|
||||
/************************************************
|
||||
@@ -2345,11 +2299,8 @@ static DeviceRef VerifyDevice(ALCdevice *device)
|
||||
std::lock_guard<std::recursive_mutex> _{ListLock};
|
||||
auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device);
|
||||
if(iter != DeviceList.cend() && *iter == device)
|
||||
{
|
||||
(*iter)->add_ref();
|
||||
return DeviceRef{iter->get()};
|
||||
}
|
||||
return DeviceRef{};
|
||||
return *iter;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -2590,14 +2541,10 @@ static ContextRef VerifyContext(ALCcontext *context)
|
||||
std::lock_guard<std::recursive_mutex> _{ListLock};
|
||||
auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context);
|
||||
if(iter != ContextList.cend() && *iter == context)
|
||||
{
|
||||
(*iter)->add_ref();
|
||||
return ContextRef{iter->get()};
|
||||
}
|
||||
return ContextRef{};
|
||||
return *iter;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/* GetContextRef
|
||||
*
|
||||
* Returns a new reference to the currently active context for this thread.
|
||||
|
||||
+3
-47
@@ -178,56 +178,12 @@ struct ALCcontext : public al::intrusive_ref<ALCcontext> {
|
||||
} while(0)
|
||||
|
||||
|
||||
void UpdateContextProps(ALCcontext *context);
|
||||
|
||||
|
||||
/* Simple RAII context reference. Takes the reference of the provided
|
||||
* ALCcontext, and decrements it when leaving scope. Movable (transfer
|
||||
* reference) but not copyable (no new references).
|
||||
*/
|
||||
class ContextRef {
|
||||
ALCcontext *mCtx{nullptr};
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
if(mCtx)
|
||||
mCtx->release();
|
||||
mCtx = nullptr;
|
||||
}
|
||||
|
||||
public:
|
||||
ContextRef() noexcept = default;
|
||||
ContextRef(ContextRef&& rhs) noexcept : mCtx{rhs.mCtx}
|
||||
{ rhs.mCtx = nullptr; }
|
||||
explicit ContextRef(ALCcontext *ctx) noexcept : mCtx(ctx) { }
|
||||
~ContextRef() { reset(); }
|
||||
|
||||
ContextRef& operator=(const ContextRef&) = delete;
|
||||
ContextRef& operator=(ContextRef&& rhs) noexcept
|
||||
{ std::swap(mCtx, rhs.mCtx); return *this; }
|
||||
|
||||
operator bool() const noexcept { return mCtx != nullptr; }
|
||||
|
||||
ALCcontext* operator->() const noexcept { return mCtx; }
|
||||
ALCcontext* get() const noexcept { return mCtx; }
|
||||
|
||||
ALCcontext* release() noexcept
|
||||
{
|
||||
ALCcontext *ret{mCtx};
|
||||
mCtx = nullptr;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool operator==(const ContextRef &lhs, const ALCcontext *rhs) noexcept
|
||||
{ return lhs.get() == rhs; }
|
||||
inline bool operator!=(const ContextRef &lhs, const ALCcontext *rhs) noexcept
|
||||
{ return !(lhs == rhs); }
|
||||
inline bool operator<(const ContextRef &lhs, const ALCcontext *rhs) noexcept
|
||||
{ return lhs.get() < rhs; }
|
||||
using ContextRef = al::intrusive_ptr<ALCcontext>;
|
||||
|
||||
ContextRef GetContextRef(void);
|
||||
|
||||
void UpdateContextProps(ALCcontext *context);
|
||||
|
||||
|
||||
extern bool TrapALError;
|
||||
|
||||
|
||||
@@ -43,6 +43,71 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename T>
|
||||
class intrusive_ptr {
|
||||
T *mPtr{nullptr};
|
||||
|
||||
public:
|
||||
intrusive_ptr() noexcept = default;
|
||||
intrusive_ptr(const intrusive_ptr &rhs) noexcept : mPtr{rhs.mPtr}
|
||||
{ if(mPtr) mPtr->add_ref(); }
|
||||
intrusive_ptr(intrusive_ptr&& rhs) noexcept : mPtr{rhs.mPtr}
|
||||
{ rhs.mPtr = nullptr; }
|
||||
intrusive_ptr(std::nullptr_t) noexcept { }
|
||||
explicit intrusive_ptr(T *ptr) noexcept : mPtr{ptr} { }
|
||||
~intrusive_ptr() { reset(); }
|
||||
|
||||
intrusive_ptr& operator=(const intrusive_ptr &rhs) noexcept
|
||||
{
|
||||
if(rhs.mPtr) rhs.mPtr->add_ref();
|
||||
if(mPtr) mPtr->release();
|
||||
mPtr = rhs.mPtr;
|
||||
return *this;
|
||||
}
|
||||
intrusive_ptr& operator=(intrusive_ptr&& rhs) noexcept
|
||||
{ std::swap(mPtr, rhs.mPtr); return *this; }
|
||||
|
||||
operator bool() const noexcept { return mPtr != nullptr; }
|
||||
|
||||
T* operator->() const noexcept { return mPtr; }
|
||||
T* get() const noexcept { return mPtr; }
|
||||
|
||||
void reset() noexcept
|
||||
{
|
||||
if(mPtr)
|
||||
mPtr->release();
|
||||
mPtr = nullptr;
|
||||
}
|
||||
|
||||
T* release() noexcept
|
||||
{
|
||||
T *ret{mPtr};
|
||||
mPtr = nullptr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void swap(intrusive_ptr &rhs) noexcept { std::swap(mPtr, rhs.mPtr); }
|
||||
void swap(intrusive_ptr&& rhs) noexcept { std::swap(mPtr, rhs.mPtr); }
|
||||
};
|
||||
|
||||
#define AL_DECL_OP(op) \
|
||||
template<typename T> \
|
||||
inline bool operator op(const intrusive_ptr<T> &lhs, const T *rhs) noexcept \
|
||||
{ return lhs.get() op rhs; } \
|
||||
template<typename T> \
|
||||
inline bool operator op(const T *lhs, const intrusive_ptr<T> &rhs) noexcept \
|
||||
{ return lhs op rhs.get(); }
|
||||
|
||||
AL_DECL_OP(==)
|
||||
AL_DECL_OP(!=)
|
||||
AL_DECL_OP(<=)
|
||||
AL_DECL_OP(>=)
|
||||
AL_DECL_OP(<)
|
||||
AL_DECL_OP(>)
|
||||
|
||||
#undef AL_DECL_OP
|
||||
|
||||
} // namespace al
|
||||
|
||||
#endif /* INTRUSIVE_PTR_H */
|
||||
|
||||
Reference in New Issue
Block a user