///////////////////////////////////////////////////////////////////////////
// FILE: memory (Utilities for manipulating memory)
//
//                          Open Watcom Project
//
// Copyright (c) 2004-2008 The Open Watcom Contributors. All Rights Reserved.
//
//    This file is automatically generated. Do not edit directly.
//
// =========================================================================
//
// Description: This header is part of the C++ standard library. It
//              defines a number of helper templates to simplify the
//              handling of raw memory.
///////////////////////////////////////////////////////////////////////////
#ifndef _MEMORY_INCLUDED
#define _MEMORY_INCLUDED

#if !defined(_ENABLE_AUTODEPEND)
  #pragma read_only_file;
#endif


#ifndef __cplusplus
#error The header memory requires C++
#endif

#ifndef _CSTDDEF_INCLUDED
  #include <cstddef>
#endif

#ifndef _ITERATOR_INCLUDED
  #include <iterator>
#endif

#ifndef _NEW_INCLUDED
  #include <new>
#endif

#ifndef _TYPEINFO_INCLUDED  
  #include <typeinfo>
#endif 

#ifndef _WC_EXCEPTION_MACROS_
  #define _WC_EXCEPTION_MACROS_
  #ifdef _CPPUNWIND
    #define _WCTHROWS( __t )  throw( __t ) // Use for exception specifications.
    #define _WCTHROW( __t )   throw( __t ) // Use for throw statements.
    #define _WCTRY            try
    #define _WCHANDLERS       1
  #else
    #define _WCTHROWS( __t )
    #define _WCTHROW( __t )
    #define _WCTRY
  #endif
#endif

template< class Iterator, class Type >
inline void _RawConstruct( Iterator ptr, const Type &value )
{
    typedef typename std::iterator_traits< Iterator >::value_type value_type;
    new ( static_cast< void * >( &*ptr ) ) value_type( value );
}

template< class Iterator >
inline void _RawDestroy( Iterator ptr )
{
    typedef typename std::iterator_traits< Iterator >::value_type value_type;
    ( *ptr ).~value_type( );
}

namespace std {

  template< class Type > class allocator;

  // Allocator specialization for void
  // *********************************

  template< >
  class allocator< void > {
  public:
    typedef void       *pointer;
    typedef const void *const_pointer;
    typedef void        value_type;

    template< class Type2 >
    struct rebind { typedef allocator< Type2 > other; };
  };

  // Default allocator template
  // **************************

  template< class Type >
  class allocator {
  public:
    typedef       std::size_t    size_type;
    typedef       std::ptrdiff_t difference_type;
    typedef       Type          *pointer;
    typedef const Type          *const_pointer;
    typedef       Type          &reference;
    typedef const Type          &const_reference;
    typedef       Type           value_type;

    template< class Type2 >
    struct rebind { typedef allocator< Type2 > other; };

    allocator( )
      { }

    allocator( const allocator & )
      { }

    template< class Type2 >
    allocator( const allocator< Type2 > & )
      { }

   ~allocator( )
      { }

    pointer address( reference r ) const
      { return( &r ); }

    const_pointer address( const_reference r ) const
      { return( &r ); }

    pointer allocate( size_type n, allocator< void >::const_pointer = 0 )
      { return( reinterpret_cast< Type * >(
                  ::operator new( n * sizeof( Type ) ) ) ); }

    void deallocate( pointer p, size_type )
      { ::operator delete( reinterpret_cast< unsigned char * >( p ) ); }

    size_type max_size( ) const
      { return 0; }  // FIX ME

    void construct( pointer p, const Type &value )
      { new ( ( void * )p ) Type( value ); }

    void destroy( pointer p )
      { ( ( Type * )p )->~Type( ); }
  };

  // Raw storage iterator
  // ********************

  template< class OutputIterator, class Type >
  class raw_storage_iterator
    : public iterator< output_iterator_tag, void, void, void, void > {
  public:
    explicit raw_storage_iterator( OutputIterator it ) : ptr( it )
      { }
    raw_storage_iterator &operator*( )
      { return( *this ); }
    raw_storage_iterator &operator=( const Type & incoming )
      { _RawConstruct( ptr, incoming ); return( *this ); }
    raw_storage_iterator &operator++( )
      { ++ptr; return( *this ); }
    raw_storage_iterator  operator++( int )
      { raw_storage_iterator temp( *this ); ++ptr; return( temp ); }
  private:
    OutputIterator ptr;
  };


  // Temporary Buffers
  // *****************

  // Need compiler support for explicit function template arguments.

  // Templates for initializing blocks of uninitialized memory
  // *********************************************************

  template< class ForwardIterator, class Type >
  void uninitialized_fill(
      ForwardIterator first,
      ForwardIterator last,
      const Type &value )
  {
      typedef
        typename iterator_traits< ForwardIterator >::value_type value_type;
      ForwardIterator bookmark( first );

      _WCTRY {
          // Construct copies of value in the raw storage.
          while( first != last ) {
              _RawConstruct( first, value );
              ++first;
          }
      }
      #ifdef _WCHANDLERS
      // If an exception occurs, destroy copies that were made successfully.
      catch( ... ) {
          while( bookmark != first ) {
              _RawDestroy( bookmark );
              ++bookmark;
          }
          throw;
      }
      #endif
  }


  template< class ForwardIterator, class Size, class Type >
  void uninitialized_fill_n(
      ForwardIterator first,
      Size n,
      const Type &value )
  {
      typedef
        typename iterator_traits< ForwardIterator >::value_type value_type;
      ForwardIterator bookmark( first );

      _WCTRY {
          // Construct n copies of value in raw storage.
          while( n-- ) {
              _RawConstruct( first, value );
              ++first;
          }
      }
      #ifdef _WCHANDLERS
      // If an exception occurs, destroy copies that were made successfully.
      catch( ... ) {
          while( bookmark != first ) {
              _RawDestroy( bookmark );
              ++bookmark;
          }
          throw;
      }
      #endif
  }


  template< class InputIterator, class ForwardIterator >
  ForwardIterator uninitialized_copy(
      InputIterator first,
      InputIterator last,
      ForwardIterator dest )
  {
      typedef
        typename iterator_traits< ForwardIterator >::value_type value_type;
      ForwardIterator bookmark( dest );

      _WCTRY {
          // Copy objects from input sequence to raw storage.
          while( first != last ) {
              _RawConstruct( dest, *first );
              ++first;
              ++dest;
          }
          return( dest );
      }
      #ifdef _WCHANDLERS
      // If an exception occurs, destroy copies that were made successfully.
      catch( ... ) {
          while( bookmark != dest ) {
              _RawDestroy( bookmark );
              ++bookmark;
          }
          throw;
      }
      #endif
  }


  // auto_ptr template
  // *****************

  template< class Type > struct auto_ptr;

  template< class Type >
  struct auto_ptr_ref {
    auto_ptr< Type > &ref;
    auto_ptr_ref( auto_ptr< Type > &r ) : ref( r ) { }
  };

  template< class Type >
  class auto_ptr {
  public:
    typedef Type element_type;

    explicit auto_ptr( Type *p = 0 ) : ptr( p )
      { }

    auto_ptr( auto_ptr &other ) : ptr( other.release( ) )
      { }

    template< class Type2 >
    auto_ptr( auto_ptr< Type2 > &other ) :
      ptr( static_cast< Type * >( other.release( ) ) )
      { }

    auto_ptr &operator=( auto_ptr &other )
      { reset( other.release( ) ); return( *this ); }

    template< class Type2 >
    auto_ptr &operator=( auto_ptr< Type2 > &other )
      { reset( static_cast< Type * >( other.release( ) ) ); return ( *this ); }

   ~auto_ptr( ) _WCTHROWS( )
      { delete ptr; }

    Type &operator*( ) const
      { return( *ptr ); }

    Type *operator->( ) const
      { return( ptr ); }

    Type *get( ) const
      { return( ptr ); }

    Type *release( )
      { Type *tmp = ptr; ptr = 0; return( tmp ); }

    void reset( Type *p = 0 ) _WCTHROWS( )
      { if ( ptr != p ) delete ptr; ptr = p; }

    auto_ptr( auto_ptr_ref< Type > r ) : ptr( r.ref.release( ) )
      { }

    // template< class Type2 > 
    // operator auto_ptr_ref< Type2 >( )
    //   { return( auto_ptr_ref< Type2 >( *this ); }

    // template< class Type2 >
    // operator auto_ptr< Type2 >( )
    //   { }

  private:
    Type *ptr;
  };
  
  
    // bad_weak_ptr class
    // ******************

    class bad_weak_ptr : public std::exception {
    public:
        bad_weak_ptr( ) { }
        virtual const char *what( ) const
            {  return "bad_weak_ptr"; }
    };



    // shared_ptr template
    // *******************

    template< class T > class weak_ptr;
    template< class T > class enable_shared_from_this;

    namespace detail {
        class shared_holder;
        template< class T > class shared_holder_ptr;
        template< class T, class D > class shared_holder_deleter;

        struct static_pointer_cast_tag { };
        struct dynamic_pointer_cast_tag { };
        struct const_pointer_cast_tag { };
    }

    template< class T > class shared_ptr {
    public:
        typedef T element_type;
        
        // constructors
        shared_ptr( ) : ptr( 0 ), holder( 0 ) { }

        template< class Y > explicit shared_ptr( Y *p ) : ptr( p )
            {
                try {
                    holder = new detail::shared_holder_ptr< T >( ptr, 1 );
                }
                catch( ... ) {
                    delete ptr;
                    throw;
                }
                check_enable_shared_from_this( p );
            }

        template< class Y, class D > shared_ptr( Y *p, D d ) : ptr( p )
            {
                try {
                    holder = new detail::shared_holder_deleter< T, D >( ptr, d, 1 );
                }
                catch( ... ) {
                    d( ptr );
                    throw;
                }
                check_enable_shared_from_this( p );
            }

        shared_ptr( shared_ptr const &r ) : ptr( r.ptr ), holder( r.holder )
            {
                if( ptr && holder )
                    holder->increase_count( );
            }
        
        template< class Y > 
        shared_ptr( shared_ptr< Y > const &r ) : ptr( r.get( ) ), holder( r.get_holder( ) )
            {
                if( ptr && holder )
                    holder->increase_count( );
            }

        template< class Y > 
        explicit shared_ptr( weak_ptr< Y > const &r ) : ptr( r.get( ) ), holder( r.get_holder( ) )
            {
                if( r.expired( ) )
                    throw bad_weak_ptr( );
                
                if( ptr && holder )
                    holder->increase_count( );
            }
        
        template< class Y > explicit shared_ptr( auto_ptr< Y > &r ) : ptr( r.get( ) ) 
            {
                holder = new detail::shared_holder_ptr< T >( ptr, 1 );
                check_enable_shared_from_this( r.release( ) );
            }

        template< class Y > 
        shared_ptr( shared_ptr< Y > const &r, detail::static_pointer_cast_tag& ) : 
        ptr( static_cast< T* >( r.ptr ) ), holder( r.holder )
            { 
                if( ptr && holder )
                    holder->increase_count( );
            }

        template< class Y > 
        shared_ptr( shared_ptr< Y > const &r, detail::dynamic_pointer_cast_tag& ) : 
        ptr( dynamic_cast< T* >( r.ptr ) ), holder( r.holder )
            { 
                if( ptr && holder )
                    holder->increase_count( );
                else
                    holder = 0;
            }

        template< class Y > 
        shared_ptr( shared_ptr< Y > const &r, detail::const_pointer_cast_tag& ) : 
        ptr( const_cast< T* >( r.ptr ) ), holder( r.holder )
            { 
                if( ptr && holder )
                    holder->increase_count( );
            }
        
        // destructor
        ~shared_ptr( )
            {
                if( holder )
                    holder->decrease_count( );
            }
        
        // assignments
        shared_ptr& operator=( shared_ptr const& r )
            {
                if( r.holder )
                    r.holder->increase_count( );
                    
                if( holder )
                    holder->decrease_count( );                    
                    
                ptr = r.ptr;
                holder = r.holder;
                    
                return *this;
            }

        template< class Y > shared_ptr& operator=( shared_ptr< Y > const &r )
            {
                if( r.get_holder( ) )
                    r.get_holder( )->increase_count( );
                
                if( holder )
                    holder->decrease_count( );
                    
                ptr = r.get( );
                holder = r.get_holder( );   
                    
                return *this;
            }
        
        template< class Y > shared_ptr& operator=( auto_ptr< Y > &r )
            {
                if( holder )
                    holder->decrease_count( );
                    
                ptr = r.get( );    
                holder = new detail::shared_holder_ptr< T >( ptr, 1 );
                check_enable_shared_from_this( r.release( ) );    
                
                return *this;
            }
        
        // modifiers
        void swap( shared_ptr &r )
            {
                T *tmp_ptr = ptr;
                detail::shared_holder *tmp_holder = holder;
                ptr = r.ptr;
                holder = r.holder;
                r.ptr = tmp_ptr;
                r.holder = tmp_holder;
            }
        
        void reset( )
            {
                if( holder )
                    holder->decrease_count( );
                    
                ptr = 0;
                holder = 0;
            }
        
        template< class Y > void reset( Y *p )
            {
                if( holder )
                    holder->decrease_count( );
                    
                ptr = p;
                try {
                    holder = new detail::shared_holder_ptr< T >( ptr, 1 );
                }
                catch( ... ) {
                    delete ptr;
                    throw;
                }
                check_enable_shared_from_this( p );
            }

        template< class Y, class D > void reset( Y *p, D d )
            {
                if( holder )
                    holder->decrease_count( );
                
                ptr = p;
                try {
                    holder = new detail::shared_holder_deleter< T, D >( ptr, d, 1 );
                }
                catch( ... ) {
                    d( ptr );
                    throw;
                }
                check_enable_shared_from_this( p );
            }
        
        // observers
        T *get( ) const
            { return ptr; }
            
        T &operator*( ) const
            { return *ptr; }
        
        T *operator->( ) const
            { return ptr; }
            
        long use_count( ) const
            { return holder ? holder->use_count( ) : 0; }
           
        bool unique( ) const
            { return holder && holder->use_count( ) == 1; }
        
        operator bool( ) const
            { return ptr != 0; }

        void *get_deleter( const type_info &ti ) const
            { return holder ? holder->get_deleter( ti ) : 0; }

        detail::shared_holder *get_holder( ) const
            { return holder; }
        
    private:
      
        T *ptr;
        detail::shared_holder *holder;

        void check_enable_shared_from_this( enable_shared_from_this< T > *e )
            { if( e ) e->weak_this = *this; }

        void check_enable_shared_from_this( void* ) { }

        friend class shared_ptr;
        friend class weak_ptr;
        //friend template< class Y, class U > 
        //bool operator< ( shared_ptr< Y > const &, shared_ptr< U > const & );
        
    };


    template< class T, class U > bool operator==( shared_ptr< T > const &a, 
                                                  shared_ptr< U > const &b )
    {
        return a.get( ) == b.get( );
    }

    template< class T, class U > bool operator!=( shared_ptr< T > const &a,
                                                  shared_ptr< U > const &b )
    {
        return a.get( ) != b.get( );
    }

    template< class T, class U > bool operator<( shared_ptr< T > const &a, 
                                                 shared_ptr< U > const &b )
    {
        return a.get_holder( ) < b.get_holder( );
    }

    /*template< class E, class T, class Y >
    basic_ostream< E, T > &operator<<( basic_ostream< E, T > &os, 
                                       shared_ptr< Y > const &p )
    {
        os << p.get( );
    }*/

    template< class T >
    void swap( shared_ptr< T > &a, shared_ptr< T > &b )
    {
        a.swap( b );
    }

    /*template< class T, class U >
    shared_ptr< T > static_pointer_cast( shared_ptr< U > const &r )
    {
        return shared_ptr< T >( r, detail::static_pointer_cast_tag( ) );        
    }*/

    /*template< class T, class U >
    shared_ptr< T > dynamic_pointer_cast( shared_ptr< U > const &r )
    {
        return shared_ptr< T >( r, detail::dynamic_pointer_cast_tag( ) );
    }*/

    /*template< class T, class U >
    shared_ptr< T > const_pointer_cast( shared_ptr< U > const &r )
    {
        return shared_ptr< T >( r, detail::const_pointer_cast_tag( ) );
    }*/

    /*template< class D, class T > D *get_deleter( shared_ptr< T > const &p )
    {
        return static_cast< D* >( p.get_deleter( typeid( D ) ) );
    }*/

    // weak_ptr template
    // *****************

    template< class T > class weak_ptr {
    public:
        typedef T element_type;

        // constructors

        weak_ptr( ) : ptr( 0 ), holder( 0 ) { }

        template< class Y > 
        weak_ptr( shared_ptr< Y > const &r ) : ptr( r.get( ) ), holder( r.get_holder( ) )
            {
                if( holder )
                    holder->increase_weak_count( );
            }

        weak_ptr( weak_ptr const &r ) : ptr( r.ptr ), holder( r.holder ) 
            {
                if( holder )
                    holder->increase_weak_count( );
            }

        template< class Y >
        weak_ptr( weak_ptr< Y > const & r ) : ptr( r.get( ) ), holder( r.get_holder( ) )
            {
                if( holder )
                    holder->increase_weak_count( );
            }

        ~weak_ptr( )
            {
                if( holder )
                    holder->decrease_weak_count( );
            }

        // assignment

        weak_ptr &operator=( weak_ptr const &r )
            { 
                if( r.holder )
                    r.holder->increase_weak_count( );
                    
                if( holder )
                    holder->decrease_weak_count( );                    
                    
                ptr = r.ptr;
                holder = r.holder;
                    
                return *this;
            }

        template< class Y > weak_ptr &operator=( weak_ptr< Y > const &r )
            { 
                if( r.get_holder( ) )
                    r.get_holder( )->increase_weak_count( );
                    
                if( holder )
                    holder->decrease_weak_count( );                    
                    
                ptr = r.get( );
                holder = r.get_holder( );
                    
                return *this;
            }

        template< class Y > weak_ptr &operator=( shared_ptr< Y > const &r )
            { 
                if( r.get_holder( ) )
                    r.get_holder( )->increase_weak_count( );
                    
                if( holder )
                    holder->decrease_weak_count( );                    
                    
                ptr = r.get( );
                holder = r.get_holder( );
                    
                return *this;
            }

        // modifiers

        void swap( weak_ptr &r )
            {
                T *tmp_ptr = ptr;
                detail::shared_holder *tmp_holder = holder;
                ptr = r.ptr;
                holder = r.holder;
                r.ptr = tmp_ptr;
                r.holder = tmp_holder;
            }

        void reset( )
            { weak_ptr( ).swap( *this ); }

        // observers

        long use_count( ) const
            { return holder ? holder->use_count( ) : 0; }

        bool expired( ) const
            { return holder ? holder->use_count( ) == 0 : true; } 

        shared_ptr< T > lock( ) const
            { 
                if( expired( ) )
                    return shared_ptr< T >( );
                else
                {
                    shared_ptr< T > tmp( *this );
                    return tmp;
                }
            }

        T *get( ) const
            { return ptr; }
        
        detail::shared_holder *get_holder( ) const
            { return holder; }

    private:
        T *ptr;
        detail::shared_holder *holder;

        //friend template< class Y > class shared_ptr< Y >;
        friend class shared_ptr;
        //friend template< class Y > class weak_ptr;
        friend class weak_ptr;
        //friend template< class Y, class U >
        //bool operator< ( weak_ptr< Y > const &, weak_ptr< U > const & );
    };

    template< class T, class U >
    bool operator<( weak_ptr< T > const &a, weak_ptr< U > const &b )
    {
        return a.get_holder( ) < b.get_holder( );
    }
    
    template< class T >
    void swap( weak_ptr< T > &a, weak_ptr< T > &b )
    {
        a.swap( b );
    }


    // enable_shared_from_this template
    // ********************************

    template< class T > class enable_shared_from_this {
    protected:
        enable_shared_from_this( ) { }
        enable_shared_from_this( enable_shared_from_this const & ) { }
        enable_shared_from_this &operator=( enable_shared_from_this const & )
            { return *this; }
        ~enable_shared_from_this( ) { }

    public:
        shared_ptr< T > shared_from_this( )
            {
                shared_ptr< T > tmp( weak_this );
                return tmp;
            }
         
        shared_ptr< T const > shared_from_this( ) const
            {
                shared_ptr< T const > tmp( weak_this );
                return tmp;
            }

    private:
        weak_ptr< T > weak_this;

        friend class shared_ptr;
    };

    namespace detail {

        class shared_holder {
        public:
            shared_holder( long _count = 0 ) : count( _count ), weak_count( 0 ) { }
            
            long use_count( ) const
                { return count; }
                
            void increase_count( )
                { ++count; }
                
            void decrease_count( )
                {
                    if( !(--count) ) {
                        delete_ptr( );
                        if( !weak_count ) {
                            delete this;
                        }
                    }
                }

            void increase_weak_count( )
                { ++weak_count; }

            void decrease_weak_count( )
                { 
                    if( !(--weak_count) ) {
                        if( !count ) {
                            delete this;
                        }
                    }
                }

            virtual void *get_deleter( const type_info & ) const
                { return 0; }
                
            virtual ~shared_holder( ) { }
                   
        private:
            long count;
            long weak_count;
            virtual void delete_ptr( ) = 0;
        };

        template< class T >
        class shared_holder_ptr : public shared_holder {
        public:
            shared_holder_ptr( T *_ptr, long _count = 0 ) : 
            shared_holder( _count), ptr( _ptr ) { }
        
        private:
            virtual void delete_ptr( )
                { delete ptr; } 
        
            T *ptr;
        };

        template< class T, class D >
        class shared_holder_deleter : public shared_holder {
        public:
            shared_holder_deleter( T *_ptr, D _d, long _count = 0 ) : 
            shared_holder( _count ), ptr( _ptr ), d( _d ) { }

        private:
            T *ptr;
            D d;
            
            virtual void delete_ptr( )
                { d( ptr ); }

            virtual void *get_deleter( const type_info &ti ) const
                { 
                    return typeid( D ) == ti ? 
                    static_cast< void* >( const_cast< D* >(&d) ) : 0; 
                }
        };

    } // namespace detail

} // namespace std.

#endif
