. Ensure thread safety
. If the counter is 0 when destructing, delete itself
. There are two counter variables: one for the shared pointer and one for the weak pointer.
// CLASS _Ref_count_base
class __declspec(novtable) _Ref_count_base {
// common code for reference counting
private:
_Atomic_counter_t _Uses = 1;
_Atomic_counter_t _Weaks = 1;
protected:
constexpr _Ref_count_base() noexcept = default; // non-atomic initializations
public:
_Ref_count_base(const _Ref_count_base&) = delete;
_Ref_count_base& operator=(const _Ref_count_base&) = delete;
bool _Incref_nz() noexcept {
// increment use count if not zero, return true if successful
auto& _Volatile_uses = reinterpret_cast<volatile long&>(_Uses);
#ifdef _M_CEE_PURE
long _Count = *_Atomic_address_as<const long>(&_Volatile_uses);
#else
long _Count = __iso_volatile_load32(reinterpret_cast<volatile int*>(&_Volatile_uses));
#endif
while (_Count != 0) {
const long _Old_value = _INTRIN_RELAXED(_InterlockedCompareExchange)(&_Volatile_uses, _Count + 1, _Count);
if (_Old_value == _Count) {
return true;
}
_Count = _Old_value;
}
return false;
}
void _Incref() noexcept {
// increment use count
_MT_INCR(_Uses);
}
void _Incwref() noexcept {
// increment weak reference count
_MT_INCR(_Weaks);
}
void _Decref() noexcept {
// decrement use count
if (_MT_DECR(_Uses) == 0) {
_Destroy();
_Decwref();
}
}
void _Decwref() noexcept {
// decrement weak reference count
if (_MT_DECR(_Weaks) == 0) {
_Delete_this();
}
}
long _Use_count() const noexcept {
return static_cast<long>(_Uses);
}
virtual void* _Get_deleter(const type_info&) const noexcept {
return nullptr;
}
}