haiku/headers/os/support/Referenceable.h
Adrien Destugues e9b8242868 Add a BConstReference class.
This is a BReference that allows only const access to the referenced
object. This was not easily possible with the existing BReference for
two reasons:
* BReference<const Type> would not work, as BReference needs to change
the reference count of the referenced object. Adding mutable and casting
where appropriate wouldwork but,
* It is now also possible to assign a BReference to a BConstReference
(to the same type, of course). The reverse is not allowed, making it
more difficult to "const cast" the referenced object (it's still
possible to "get" the object pointer and cast that).

BConstReference can be used to provide shared read-only access to an
object, for example this can be used to cache non-copiable or
expansive to create objects.
2015-01-26 10:50:48 +01:00

202 lines
3.1 KiB
C++

/*
* Copyright 2004-2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#ifndef _REFERENCEABLE_H
#define _REFERENCEABLE_H
#include <SupportDefs.h>
// #pragma mark - BReferenceable
class BReferenceable {
public:
BReferenceable();
virtual ~BReferenceable();
// acquire and release return
// the previous ref count
int32 AcquireReference();
int32 ReleaseReference();
int32 CountReferences() const
{ return fReferenceCount; }
protected:
virtual void FirstReferenceAcquired();
virtual void LastReferenceReleased();
protected:
int32 fReferenceCount;
};
// #pragma mark - BReference
template<typename Type = BReferenceable, typename ConstType = Type>
class BReference {
public:
BReference()
:
fObject(NULL)
{
}
BReference(Type* object, bool alreadyHasReference = false)
:
fObject(NULL)
{
SetTo(object, alreadyHasReference);
}
BReference(const BReference<Type>& other)
:
fObject(NULL)
{
SetTo(other.Get());
}
template<typename OtherType>
BReference(const BReference<OtherType>& other)
:
fObject(NULL)
{
SetTo(other.Get());
}
~BReference()
{
Unset();
}
void SetTo(Type* object, bool alreadyHasReference = false)
{
if (object != NULL && !alreadyHasReference)
object->AcquireReference();
Unset();
fObject = object;
}
void Unset()
{
if (fObject) {
fObject->ReleaseReference();
fObject = NULL;
}
}
ConstType* Get() const
{
return fObject;
}
ConstType* Detach()
{
Type* object = fObject;
fObject = NULL;
return object;
}
ConstType& operator*() const
{
return *fObject;
}
ConstType* operator->() const
{
return fObject;
}
operator ConstType*() const
{
return fObject;
}
BReference& operator=(const BReference<Type, ConstType>& other)
{
SetTo(other.fObject);
return *this;
}
BReference& operator=(Type* other)
{
SetTo(other);
return *this;
}
template<typename OtherType, typename OtherConstType>
BReference& operator=(const BReference<OtherType, OtherConstType>& other)
{
SetTo(other.Get());
return *this;
}
bool operator==(const BReference<Type, ConstType>& other) const
{
return fObject == other.fObject;
}
bool operator==(const Type* other) const
{
return fObject == other;
}
bool operator!=(const BReference<Type, ConstType>& other) const
{
return fObject != other.fObject;
}
bool operator!=(const Type* other) const
{
return fObject != other;
}
private:
Type* fObject;
};
// #pragma mark - BReference
template<typename Type = BReferenceable>
class BConstReference: public BReference<Type, const Type> {
public:
BConstReference()
:
BReference<Type, const Type>()
{
}
BConstReference(Type* object, bool alreadyHasReference = false)
:
BReference<Type, const Type>(object, alreadyHasReference)
{
}
BConstReference(const BReference<Type>& other)
:
BReference<Type, const Type>(other)
{
}
// Allow assignment of a const reference from a mutable one (but not the
// reverse).
BConstReference& operator=(const BReference<Type, Type>& other)
{
SetTo(other.Get());
return *this;
}
};
#endif // _REFERENCEABLE_H