167 lines
3.8 KiB
C++
167 lines
3.8 KiB
C++
/*
|
|
* Copyright (C) 2011 The Android Open Source Project
|
|
*
|
|
* 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 __SMART_PTR_H
|
|
#define __SMART_PTR_H
|
|
|
|
#include <cutils/threads.h>
|
|
#include <cutils/atomic.h>
|
|
|
|
template <class T, bool threadSafe = false>
|
|
class SmartPtr
|
|
{
|
|
public:
|
|
explicit SmartPtr(T* ptr = (T*)NULL) {
|
|
if (threadSafe) {
|
|
m_lock = new mutex_t;
|
|
mutex_init(m_lock);
|
|
}
|
|
else m_lock = NULL;
|
|
|
|
m_ptr = ptr;
|
|
if (ptr)
|
|
m_pRefCount = new int32_t(1);
|
|
else
|
|
m_pRefCount = NULL;
|
|
}
|
|
|
|
SmartPtr<T,threadSafe>(const SmartPtr<T,false>& rhs) {
|
|
if (threadSafe) {
|
|
m_lock = new mutex_t;
|
|
mutex_init(m_lock);
|
|
}
|
|
else m_lock = NULL;
|
|
|
|
m_pRefCount = rhs.m_pRefCount;
|
|
m_ptr = rhs.m_ptr;
|
|
use();
|
|
}
|
|
|
|
SmartPtr<T,threadSafe>(SmartPtr<T,true>& rhs) {
|
|
if (threadSafe) {
|
|
m_lock = new mutex_t;
|
|
mutex_init(m_lock);
|
|
}
|
|
else m_lock = NULL;
|
|
|
|
if (rhs.m_lock) mutex_lock(rhs.m_lock);
|
|
m_pRefCount = rhs.m_pRefCount;
|
|
m_ptr = rhs.m_ptr;
|
|
use();
|
|
if (rhs.m_lock) mutex_unlock(rhs.m_lock);
|
|
}
|
|
|
|
~SmartPtr() {
|
|
if (m_lock) mutex_lock(m_lock);
|
|
release();
|
|
if (m_lock)
|
|
{
|
|
mutex_unlock(m_lock);
|
|
mutex_destroy(m_lock);
|
|
delete m_lock;
|
|
}
|
|
}
|
|
|
|
T* Ptr() const {
|
|
return m_ptr;
|
|
}
|
|
|
|
const T* constPtr() const
|
|
{
|
|
return m_ptr;
|
|
}
|
|
|
|
T* operator->() const {
|
|
return m_ptr;
|
|
}
|
|
|
|
T& operator*() const {
|
|
return *m_ptr;
|
|
}
|
|
|
|
operator void*() const {
|
|
return (void *)m_ptr;
|
|
}
|
|
|
|
// This gives STL lists something to compare.
|
|
bool operator <(const SmartPtr<T>& t1) const {
|
|
return m_ptr < t1.m_ptr;
|
|
}
|
|
|
|
SmartPtr<T,threadSafe>& operator=(const SmartPtr<T,false>& rhs)
|
|
{
|
|
if (m_ptr == rhs.m_ptr)
|
|
return *this;
|
|
|
|
if (m_lock) mutex_lock(m_lock);
|
|
release();
|
|
m_pRefCount = rhs.m_pRefCount;
|
|
m_ptr = rhs.m_ptr;
|
|
use();
|
|
if (m_lock) mutex_unlock(m_lock);
|
|
|
|
return *this;
|
|
}
|
|
|
|
SmartPtr<T,threadSafe>& operator=(SmartPtr<T,true>& rhs)
|
|
{
|
|
if (m_ptr == rhs.m_ptr)
|
|
return *this;
|
|
|
|
if (m_lock) mutex_lock(m_lock);
|
|
release();
|
|
if (rhs.m_lock) mutex_lock(rhs.m_lock);
|
|
m_pRefCount = rhs.m_pRefCount;
|
|
m_ptr = rhs.m_ptr;
|
|
use();
|
|
if (rhs.m_lock) mutex_unlock(rhs.m_lock);
|
|
if (m_lock) mutex_unlock(m_lock);
|
|
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
int32_t *m_pRefCount;
|
|
mutex_t *m_lock;
|
|
T* m_ptr;
|
|
|
|
// Increment the reference count on this pointer by 1.
|
|
int use() {
|
|
if (!m_pRefCount) return 0;
|
|
return android_atomic_inc(m_pRefCount) + 1;
|
|
}
|
|
|
|
// Decrement the reference count on the pointer by 1.
|
|
// If the reference count goes to (or below) 0, the pointer is deleted.
|
|
int release() {
|
|
if (!m_pRefCount) return 0;
|
|
|
|
int iVal = android_atomic_dec(m_pRefCount);
|
|
if (iVal > 1)
|
|
return iVal - 1;
|
|
|
|
delete m_pRefCount;
|
|
m_pRefCount = NULL;
|
|
|
|
if (m_ptr) {
|
|
delete m_ptr;
|
|
m_ptr = NULL;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
};
|
|
|
|
#endif // of __SMART_PTR_H
|