2014-01-11 00:30:39 +00:00
|
|
|
/*
|
|
|
|
******************************************************************************
|
|
|
|
* Copyright (C) 2014, International Business Machines
|
|
|
|
* Corporation and others. All Rights Reserved.
|
|
|
|
******************************************************************************
|
|
|
|
* sharedobject.h
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __SHAREDOBJECT_H__
|
|
|
|
#define __SHAREDOBJECT_H__
|
|
|
|
|
|
|
|
|
|
|
|
#include "unicode/uobject.h"
|
|
|
|
#include "umutex.h"
|
|
|
|
|
|
|
|
U_NAMESPACE_BEGIN
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Base class for shared, reference-counted, auto-deleted objects.
|
|
|
|
* Subclasses can be immutable.
|
|
|
|
* If they are mutable, then they must implement their copy constructor
|
|
|
|
* so that copyOnWrite() works.
|
|
|
|
*
|
|
|
|
* Either stack-allocate, use LocalPointer, or use addRef()/removeRef().
|
|
|
|
* Sharing requires reference-counting.
|
|
|
|
*/
|
|
|
|
class U_COMMON_API SharedObject : public UObject {
|
|
|
|
public:
|
2014-08-20 21:46:02 +00:00
|
|
|
/** Initializes totalRefCount, softRefCount to 0. */
|
|
|
|
SharedObject() : totalRefCount(0), softRefCount(0) {}
|
|
|
|
|
|
|
|
/** Initializes totalRefCount, softRefCount to 0. */
|
|
|
|
SharedObject(const SharedObject &other)
|
|
|
|
: UObject(other),
|
|
|
|
totalRefCount(0),
|
|
|
|
softRefCount(0) {}
|
2014-01-11 00:30:39 +00:00
|
|
|
|
|
|
|
virtual ~SharedObject();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Increments the number of references to this object. Thread-safe.
|
|
|
|
*/
|
|
|
|
void addRef() const;
|
|
|
|
|
|
|
|
/**
|
2014-08-20 21:46:02 +00:00
|
|
|
* Increments the number of soft references to this object. Thread-safe.
|
|
|
|
*/
|
|
|
|
void addSoftRef() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Decrements the number of references to this object. Thread-safe.
|
2014-01-11 00:30:39 +00:00
|
|
|
*/
|
|
|
|
void removeRef() const;
|
|
|
|
|
|
|
|
/**
|
2014-08-20 21:46:02 +00:00
|
|
|
* Decrements the number of soft references to this object. Thread-safe.
|
|
|
|
*/
|
|
|
|
void removeSoftRef() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the reference counter including soft references.
|
|
|
|
* Uses a memory barrier.
|
2014-01-11 00:30:39 +00:00
|
|
|
*/
|
|
|
|
int32_t getRefCount() const;
|
|
|
|
|
2014-08-20 21:46:02 +00:00
|
|
|
/**
|
|
|
|
* Returns the count of soft references only. Uses a memory barrier.
|
|
|
|
* Used for testing the cache. Regular clients won't need this.
|
|
|
|
*/
|
|
|
|
int32_t getSoftRefCount() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If allSoftReferences() == TRUE then this object has only soft
|
|
|
|
* references. The converse is not necessarily true.
|
|
|
|
*/
|
|
|
|
UBool allSoftReferences() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deletes this object if it has no references or soft references.
|
|
|
|
*/
|
2014-01-11 00:30:39 +00:00
|
|
|
void deleteIfZeroRefCount() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a writable version of ptr.
|
|
|
|
* If there is exactly one owner, then ptr itself is returned as a
|
|
|
|
* non-const pointer.
|
|
|
|
* If there are multiple owners, then ptr is replaced with a
|
|
|
|
* copy-constructed clone,
|
|
|
|
* and that is returned.
|
|
|
|
* Returns NULL if cloning failed.
|
|
|
|
*
|
|
|
|
* T must be a subclass of SharedObject.
|
|
|
|
*/
|
|
|
|
template<typename T>
|
|
|
|
static T *copyOnWrite(const T *&ptr) {
|
|
|
|
const T *p = ptr;
|
|
|
|
if(p->getRefCount() <= 1) { return const_cast<T *>(p); }
|
|
|
|
T *p2 = new T(*p);
|
|
|
|
if(p2 == NULL) { return NULL; }
|
|
|
|
p->removeRef();
|
|
|
|
ptr = p2;
|
|
|
|
p2->addRef();
|
|
|
|
return p2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Makes dest an owner of the object pointed to by src while adjusting
|
|
|
|
* reference counts and deleting the previous object dest pointed to
|
|
|
|
* if necessary. Before this call is made, dest must either be NULL or
|
2014-04-02 20:12:02 +00:00
|
|
|
* be included in the reference count of the object it points to.
|
2014-01-11 00:30:39 +00:00
|
|
|
*
|
|
|
|
* T must be a subclass of SharedObject.
|
|
|
|
*/
|
|
|
|
template<typename T>
|
|
|
|
static void copyPtr(const T *src, const T *&dest) {
|
|
|
|
if(src != dest) {
|
|
|
|
if(dest != NULL) { dest->removeRef(); }
|
|
|
|
dest = src;
|
|
|
|
if(src != NULL) { src->addRef(); }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2014-04-02 20:12:02 +00:00
|
|
|
* Equivalent to copyPtr(NULL, dest).
|
2014-01-11 00:30:39 +00:00
|
|
|
*/
|
|
|
|
template<typename T>
|
|
|
|
static void clearPtr(const T *&ptr) {
|
|
|
|
if (ptr != NULL) {
|
|
|
|
ptr->removeRef();
|
|
|
|
ptr = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2014-08-20 21:46:02 +00:00
|
|
|
mutable u_atomic_int32_t totalRefCount;
|
|
|
|
mutable u_atomic_int32_t softRefCount;
|
2014-01-11 00:30:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
U_NAMESPACE_END
|
|
|
|
|
|
|
|
#endif
|