blob: 8201e189c2f36cf4f60df28529de61093ec0f65a [file] [log] [blame]
/*
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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 CV_SHARED_PTR_H_INCLUDED
#define CV_SHARED_PTR_H_INCLUDED
#ifdef _WIN32
#include <Windows.h>
#endif
namespace
{
struct AtomicCounter
{
inline AtomicCounter(long x) : val(x)
{
}
inline long operator++()
{
#ifdef __GNUC__
return __sync_add_and_fetch(&val, 1);
#elif _MSC_VER
return InterlockedIncrement(&val);
#endif
}
inline long operator--()
{
#ifdef __GNUC__
return __sync_sub_and_fetch(&val, 1);
#elif _MSC_VER
return InterlockedDecrement(&val);
#endif
}
private:
long val;
};
typedef AtomicCounter RefCounterT;
struct Holder
{
inline Holder(void* t) : target(t), count(1)
{
}
inline void inc()
{
++count;
}
template <class T> inline void dec()
{
if (--count <= 0)
{
delete (T*) target;
delete this;
}
}
void* target;
RefCounterT count;
};
}
template <class From, class To> inline bool RequireConvertible()
{
To* oth = (From*)0;
return oth == NULL;
}
/*
* TODO: support alias-constructed pointers, add relational operators,
* support deleters, add the rest of the standard methods (swap, reset, use_count, etc.)
*/
template <class T> class shared_ptr
{
public:
template <typename U> friend class shared_ptr;
typedef T element_type;
shared_ptr() : holder(NULL)
{
}
explicit shared_ptr(element_type* t) : holder(new Holder(t))
{
}
shared_ptr(const shared_ptr& x, T* p) : holder(x.holder)
{
if (holder)
{
holder->inc();
}
}
~shared_ptr()
{
if (holder)
{
holder->dec<element_type>();
}
}
shared_ptr(const shared_ptr& x) : holder(x.holder)
{
if (holder)
{
holder->inc();
}
}
template <class U> shared_ptr(const shared_ptr<U>& x)
{
RequireConvertible<U, element_type>();
holder = x.holder;
if (holder)
{
holder->inc();
}
}
shared_ptr& operator=(const shared_ptr& x)
{
if (x.holder)
{
x.holder->inc();
}
if (holder)
{
holder->dec<T>();
}
holder = x.holder;
return *this;
}
template <class U> shared_ptr& operator=(const shared_ptr<U>& x)
{
RequireConvertible<U, element_type>();
if (x.holder)
{
x.holder->inc();
}
if (holder)
{
holder->dec<T>();
}
holder = x.holder;
return *this;
}
element_type* operator->() const
{
if (!holder)
{
return NULL;
}
return (element_type*)holder->target;
}
element_type& operator*() const
{
return *operator->();
}
element_type* get() const
{
return operator->();
}
private:
Holder* holder;
};
template <typename T, typename U> bool operator==(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs)
{
return lhs.get() == rhs.get();
}
template <typename T, typename U> bool operator!=(const shared_ptr<T>& lhs, const shared_ptr<U>& rhs)
{
return !(lhs == rhs);
}
template <typename T> bool operator<(const shared_ptr<T>& lhs, const shared_ptr<T>& rhs)
{
return lhs.get() < rhs.get();
}
template<typename T> shared_ptr<T> make_shared() { return shared_ptr<T>(new T()); }
template<typename T, typename Arg1> shared_ptr<T> make_shared(const Arg1& arg1) { return shared_ptr<T>(new T(arg1)); }
template<typename T, typename Arg1, typename Arg2> shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2) { return shared_ptr<T>(new T(arg1, arg2)); }
template<typename T, typename Arg1, typename Arg2, typename Arg3> shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) { return shared_ptr<T>(new T(arg1, arg2, arg3)); }
template<typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> shared_ptr<T> make_shared(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3, const Arg4& arg4) { return shared_ptr<T>(new T(arg1, arg2, arg3, arg4)); }
template <class T, class U> inline shared_ptr<T> static_pointer_cast(const shared_ptr<U>& x)
{
return shared_ptr<T>(x, static_cast<T*>(x.get()));
}
template <class T, class U> inline shared_ptr<T> const_pointer_cast(const shared_ptr<U>& x)
{
return shared_ptr<T>(x, const_cast<T*>(x.get()));
}
template <class T, class U> inline shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& x)
{
if (T* p = dynamic_cast<T*>(x.get()))
{
return shared_ptr<T>(x, p);
}
return shared_ptr<T>();
}
#endif // CV_SHARED_PTR_H_INCLUDED