//  Copyright (c) 2001 Daniel C. Nuffer
//  Copyright (c) 2001-2011 Hartmut Kaiser
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#if !defined(BOOST_SPIRIT_ITERATOR_REF_COUNTED_POLICY_MAR_16_2007_1108AM)
#define BOOST_SPIRIT_ITERATOR_REF_COUNTED_POLICY_MAR_16_2007_1108AM

#include <boost/spirit/home/support/iterators/multi_pass_fwd.hpp>
#include <boost/spirit/home/support/iterators/detail/multi_pass.hpp>
#if defined(BOOST_HAS_THREADS)
#include <boost/detail/atomic_count.hpp>
#endif
#include <cstdlib>

namespace boost {
namespace spirit {
namespace iterator_policies {
///////////////////////////////////////////////////////////////////////////
//  class ref_counted
//  Implementation of an OwnershipPolicy used by multi_pass.
//
//  Implementation modified from RefCounted class from the Loki library by
//  Andrei Alexandrescu.
///////////////////////////////////////////////////////////////////////////
struct ref_counted
{
    ///////////////////////////////////////////////////////////////////////
    struct unique // : detail::default_ownership_policy
    {
        void
        swap(unique&) {}

        // clone is called when a copy of the iterator is made, so
        // increment the ref-count.
        template <typename MultiPass>
        static void
        clone(MultiPass& mp)
        {
            if (0 != mp.shared())
            {
                ++mp.shared()->count;
            }
        }

        // called when a copy is deleted. Decrement the ref-count. Return
        // value of true indicates that the last copy has been released.
        template <typename MultiPass>
        static bool
        release(MultiPass& mp)
        {
            return 0 != mp.shared() && 0 == --mp.shared()->count;
        }

        // returns true if there is only one iterator in existence.
        // std_deque StoragePolicy will free it's buffered data if this
        // returns true.
        template <typename MultiPass>
        static bool
        is_unique(MultiPass const& mp)
        {
            return 0 == mp.shared() || 1 == mp.shared()->count;
        }

        template <typename MultiPass>
        static void
        destroy(MultiPass&) {}
    };

    ////////////////////////////////////////////////////////////////////////
    struct shared
    {
        shared() : count(1) {}

#if defined(BOOST_HAS_THREADS)
        boost::detail::atomic_count count;
#else
        std::size_t count;
#endif
    };

};

}
}
}

#endif
