// Copyright (C) 2007 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_WEAK_PTr_
#define DLIB_WEAK_PTr_
#include <algorithm>
#include <memory>
#include "shared_ptr.h"
#include "../algs.h"
#include "weak_ptr_abstract.h"
namespace dlib {
template <
typename T
>
class weak_ptr
{
/*!
CONVENTION
- if (weak_node != 0) then
- data == valid pointer to shared data
- weak_node->ref_count == the number of weak_ptrs that reference this->data
- else
- data == 0
- expired() == ((weak_node == 0) || (weak_node->shared_node == 0))
- if (expired() == false) then
- use_count() == weak_node->shared_node->ref_count
- else
- use_count() == 0
!*/
public:
typedef T element_type;
weak_ptr(
) : data(0), weak_node(0)
{
}
template<typename Y>
weak_ptr(
const shared_ptr<Y>& r
)
{
data = r.data;
if (r.shared_node)
{
if (r.shared_node->weak_node)
{
weak_node = r.shared_node->weak_node;
weak_node->ref_count += 1;
}
else
{
weak_node = new weak_ptr_node(r.shared_node);
r.shared_node->weak_node = weak_node;
}
}
else
{
weak_node = 0;
}
}
weak_ptr(
const weak_ptr& r
)
{
data = r.data;
weak_node = r.weak_node;
if (weak_node)
weak_node->ref_count += 1;
}
template<typename Y>
weak_ptr(
const weak_ptr<Y>& r
)
{
data = r.data;
weak_node = r.weak_node;
if (weak_node)
weak_node->ref_count += 1;
}
~weak_ptr(
)
{
if (weak_node)
{
// make note that this weak_ptr is being destroyed
weak_node->ref_count -= 1;
// if this is the last weak_ptr then we should clean up our stuff
if (weak_node->ref_count == 0)
{
if (expired() == false)
weak_node->shared_node->weak_node = 0;
delete weak_node;
}
}
}
weak_ptr& operator= (
const weak_ptr& r
)
{
weak_ptr(r).swap(*this);
return *this;
}
template<typename Y>
weak_ptr& operator= (
const weak_ptr<Y>& r
)
{
weak_ptr(r).swap(*this);
return *this;
}
template<typename Y>
weak_ptr& operator=(
const shared_ptr<Y>& r
)
{
weak_ptr(r).swap(*this);
return *this;
}
long use_count(
) const
{
if (expired())
return 0;
else
return weak_node->shared_node->ref_count;
}
bool expired() const { return weak_node == 0 || weak_node->shared_node == 0; }
shared_ptr<T> lock(
) const
{
if (expired())
return shared_ptr<T>();
else
return shared_ptr<T>(*this);
}
void reset(
)
{
weak_ptr().swap(*this);
}
void swap(
weak_ptr<T>& b
)
{
std::swap(data, b.data);
std::swap(weak_node, b.weak_node);
}
template <typename Y>
bool _private_less (
const weak_ptr<Y>& rhs
) const
{
if (expired())
{
if (rhs.expired())
{
return false;
}
else
{
return true;
}
}
else
{
if (rhs.expired())
{
return false;
}
else
{
// in this case they have both not expired so lets
// compare the shared_node pointers
return (weak_node->shared_node) < (rhs.weak_node->shared_node);
}
}
}
private:
template <typename Y> friend class shared_ptr;
template <typename Y> friend class weak_ptr;
T* data;
weak_ptr_node* weak_node;
};
template<typename T, typename U>
bool operator< (
const weak_ptr<T>& a,
const weak_ptr<U>& b
)
{
return a._private_less(b);
}
template<typename T>
void swap(
weak_ptr<T>& a,
weak_ptr<T> & b
) { a.swap(b); }
}
#endif // DLIB_WEAK_PTr_