// Copyright (C) 2004  Davis E. King (davisking@users.sourceforge.net)
// License: Boost Software License   See LICENSE.txt for the full license.
#undef DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_
#ifdef DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_

#include "../algs.h"

namespace dlib
{
    template <
        typename T
        >
    class memory_manager
    {
        /*!      
            REQUIREMENTS ON T
                T must have a default constructor.      

            INITIAL VALUE
                get_number_of_allocations() == 0

            WHAT THIS OBJECT REPRESENTS
                This object represents some kind of memory manager or memory pool.
        !*/
        
        public:

            typedef T type;

            template <typename U>
            struct rebind {
                typedef memory_manager<U> other;
            };

            memory_manager(
            );
            /*!
                ensures 
                    - #*this is properly initialized
                throws
                    - std::bad_alloc
            !*/

            virtual ~memory_manager(
            ); 
            /*!
                ensures
                    - if (get_number_of_allocations() == 0) then
                        - all resources associated with *this have been released.
                    - else
                        - The memory still allocated will not be deleted and this
                          causes a memory leak. 
            !*/

            unsigned long get_number_of_allocations (
            ) const;
            /*!
                ensures
                    - returns the current number of outstanding allocations
            !*/
 
            T* allocate (
            );
            /*!
                ensures
                    - allocates a new object of type T and returns a pointer to it.
                    - #get_number_of_allocations() == get_number_of_allocations() + 1
                throws
                    - std::bad_alloc or any exception thrown by T's constructor.
                        If this exception is thrown then the call to allocate() 
                        has no effect on #*this.
            !*/

            void deallocate (
                T* item
            );
            /*!
                requires
                    - item == is a pointer to memory that was obtained from a call to
                      this->allocate(). (i.e. you can't deallocate a pointer you
                      got from a different memory_manager instance.)
                    - the memory pointed to by item hasn't already been deallocated.
                ensures
                    - deallocates the object pointed to by item
                    - #get_number_of_allocations() == get_number_of_allocations() - 1
            !*/

            T* allocate_array (
                unsigned long size
            );
            /*!
                ensures
                    - allocates a new array of size objects of type T and returns a 
                      pointer to it.
                    - #get_number_of_allocations() == get_number_of_allocations() + 1
                throws
                    - std::bad_alloc or any exception thrown by T's constructor.
                        If this exception is thrown then the call to allocate() 
                        has no effect on #*this.
            !*/

            void deallocate_array (
                T* item
            );
            /*!
                requires
                    - item == is a pointer to memory that was obtained from a call to
                      this->allocate_array(). (i.e. you can't deallocate a pointer you
                      got from a different memory_manager instance and it must be an
                      array.)
                    - the memory pointed to by item hasn't already been deallocated.
                ensures
                    - deallocates the array pointed to by item
                    - #get_number_of_allocations() == get_number_of_allocations() - 1
            !*/

            void swap (
                memory_manager& item
            );
            /*!
                ensures
                    - swaps *this and item
            !*/ 

        private:

            // restricted functions
            memory_manager(memory_manager&);        // copy constructor
            memory_manager& operator=(memory_manager&);    // assignment operator
    };

    template <
        typename T
        >
    inline void swap (
        memory_manager<T>& a, 
        memory_manager<T>& b 
    ) { a.swap(b); }   
    /*!
        provides a global swap function
    !*/

}

#endif // DLIB_MEMORY_MANAGER_KERNEl_ABSTRACT_

