Add and use an intrusive_ptr type

This commit is contained in:
Chris Robinson
2019-08-01 15:19:37 -07:00
parent 57e7fff6f6
commit 0be823320d
3 changed files with 73 additions and 105 deletions
+5 -58
View File
@@ -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
View File
@@ -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;
+65
View File
@@ -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 */