blob: 15477eb83cc41a890224bc68a638a4e61c1cebb0 [file] [log] [blame]
/* ------------------------------------------------------------------
* Copyright (C) 1998-2009 PacketVideo
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied.
* See the License for the specific language governing permissions
* and limitations under the License.
* -------------------------------------------------------------------
*/
#ifndef PVMF_COUNTED_PTR_H_INCLUDED
#define PVMF_COUNTED_PTR_H_INCLUDED
#ifndef OSCL_BASE_H_INCLUDED
#include "oscl_base.h"
#endif
#ifndef OSCL_MEM_H_INCLUDED
#include "oscl_mem.h"
#endif
#ifndef OSCL_MEM_MEMPOOL_H_INCLUDED
#include "oscl_mem_mempool.h"
#endif
template <class T>
class PVMFReferenceCounter : public OsclRefCounter
{
public:
//This is the surrogate constructor.
//It allocates the ReferenceCounter from it's own pool
//so it can manage the deallocation later, when the time is right.
static PVMFReferenceCounter<T>* create(void)
{
//Check if the memory pools need to be setup.
if (!poolrc)
{
rcPool = OSCL_NEW
(
OsclMemPoolFixedChunkAllocator,
(
poolDepth/*chunks*/
, sizeof(PVMFReferenceCounter<T>)/*chunk size*/
, NULL/*allocator*/
)
);
tPool = OSCL_NEW
(
OsclMemPoolFixedChunkAllocator,
(
poolDepth/*chunks*/
, sizeof(T)/*chunk size*/
, NULL/*allocator*/
)
);
}
//Increment the pool's ref counter each time we allocate from it.
poolrc++;
//Allocate the template object from the pool.
T* thisObj = OSCL_STATIC_CAST(T*, tPool->allocate(sizeof(T)));
//Construct the object in place using it's default constructor.
thisObj = OSCL_PLACEMENT_NEW(thisObj, T());
//Allocate "this" ReferenceCounter from the pool.
PVMFReferenceCounter<T>* thisRC =
OSCL_STATIC_CAST(PVMFReferenceCounter<T>*,
rcPool->allocate(sizeof(PVMFReferenceCounter<T>)));
//Construct the ReferenceCounter in place.
thisRC = OSCL_PLACEMENT_NEW(thisRC, PVMFReferenceCounter<T>(thisObj));
return thisRC;
}
virtual void addRef()
{
rc++;
}
virtual void removeRef()
{
rc--;
if (!rc)
{
obj->~T();
tPool->deallocate(obj);
rcPool->deallocate(this);
poolrc--;
if (!poolrc)
{
OSCL_DELETE(rcPool);
OSCL_DELETE(tPool);
}
}
}
virtual uint32 getCount()
{
return rc;
}
//The actual reference count.
uint32 rc;
//The object to which were are counting references.
T* obj;
private:
//These are the memory pools from which the reference counter
//and template object are instantiated. These are fixed-chunk
//allocators to optimize allocation speed.
static OsclMemPoolFixedChunkAllocator* rcPool;
static OsclMemPoolFixedChunkAllocator* tPool;
//This is the reference counter for the memory pools so we know when to free them.
static uint32 poolrc;
//This is the size of the memory pool in whole-unit allocations.
static uint32 poolDepth;
//The default constructor is private to prevent accidentally
//allocating one incorrectly. The proper way to allocate a
//ReferenceCounter is to call the "create" method AFTER initializing
//the OSCL memory subsystem.
PVMFReferenceCounter(T* aObj = NULL)
: rc(1)
, obj(aObj)
{
}
};
/**
*@note: Because CounterPtr creates a ReferenceCounter,
* you cannot instantiate a CounterPtr before calling OsclMem::Init().
*/
template <class T>
class PVMFCountedPtr
{
public:
PVMFReferenceCounter<T>* cnt;
PVMFCountedPtr(void)
{
cnt = PVMFReferenceCounter<T>::create();
}
~PVMFCountedPtr()
{
cnt->removeRef();
}
PVMFCountedPtr<T>& operator=(const PVMFCountedPtr<T>& r)
{
//Order of statements is important.
//Must add ref first in case r==this.
r.cnt->addRef();
//Detach the old ref counter.
cnt->removeRef();
//Attach the new ref counter.
cnt = r.cnt;
return *this;
}
inline T& operator*() const
{
return *(cnt->obj);
}
inline T* operator->() const
{
return cnt->obj;
}
};
#endif //PVMF_COUNTED_PTR_H_INCLUDED