    // file      : Utility/ReferenceCounting/DefaultImpl.hpp
    // author    : Boris Kolpackov <boris@kolpackov.net>
    // copyright : Copyright (c) 2002-2003 Boris Kolpackov
    // license   : http://kolpackov.net/license.html

    namespace Utility
    {
      namespace ReferenceCounting
      {
        // Default reference counter implementation with parameterised
        // synchronization policy. It is assumed that none of the SynchPolicy
        // types throw any logic exceptions. If in fact they do then these
        // exceptions won't be handled and will be automatically converted
        // to system exceptions.

        template <typename SynchPolicy = Utility::Synch::Policy::Null>
        class DefaultImpl : public virtual Interface
        {
        public:
          class InconsistentState_ {};
          typedef
          ExH::Compound<InconsistentState_, Exception>
          InconsistentState;

        public:
          DefaultImpl () throw (SystemException);

          virtual
          ~DefaultImpl () throw ();

        public:
          virtual void
          add_ref () const throw (Exception, SystemException);

          virtual void
          remove_ref () const throw ();

          virtual count_t
          refcount_value () const throw (Exception, SystemException);

        protected:
          virtual void
          add_ref_i () const throw (Exception, SystemException);

          virtual bool
          remove_ref_i () const throw (Exception, SystemException);

          virtual count_t
          refcount_value_i () const throw (Exception, SystemException);

          typename SynchPolicy::Mutex&
          lock_i () const throw ();

        protected:
          typedef
          typename SynchPolicy::Mutex
          Mutex_;

          typedef
          typename SynchPolicy::ReadGuard
          ReadGuard_;

          typedef
          typename SynchPolicy::WriteGuard
          WriteGuard_;

        protected:
          mutable count_t ref_count_;

        private:
          mutable Mutex_  lock_;

        private:
          // Copy semanic is not supported.
          DefaultImpl (DefaultImpl const&) throw ();
          DefaultImpl&
          operator= (DefaultImpl const&) throw ();
        };
      }
    }