How to track memory usage using EASTL?

后端 未结 1 861
逝去的感伤
逝去的感伤 2021-01-24 12:31

The Electronic Arts EASTL library\'s east::allocator requires the user to implement a special new operator (as shown in this sample). This new

相关标签:
1条回答
  • 2021-01-24 12:57

    The allocators by the EASTL are stateful and bound to the instance of the container; meaning they are defined at instance level:

    What EASTL does is use a more familiar memory allocation pattern whereby there is only one allocator class interface and it is used by all containers. Additionally EASTL containers let you access their allocators and query them, name them, change them, etc.

    EASTL has chosen to make allocators not be copied between containers during container swap and assign operations. This means that if container A swaps its contents with container B, both containers retain their original allocators. Similarly, assigning container A to container B causes container B to retain its original allocator. Containers that are equivalent should report so via operator==; EASTL will do a smart swap if allocators are equal, and a brute-force swap otherwise.

    from https://github.com/questor/eastl/blob/master/doc/EASTL%20Design.html

    So I would add a member to the allocator class and track the memory count inside it, like following:

    #ifndef EASTL_CUSTOM_ALLOCATOR_H_
    #define EASTL_CUSTOM_ALLOCATOR_H_
    
    #include "new_implementation.hpp"
    #include <EASTL/list.h>
    #include <iostream>
    
    #define DEBUG_MACRO
    
    class EASTL_CustomAllocator {
    public:
        EASTL_CustomAllocator(const char* pName = EASTL_NAME_VAL(EASTL_ALLOCATOR_DEFAULT_NAME))
            : m_pName(pName), m_totalAmountOfBytesAllocated(0) {
    #ifdef DEBUG_MACRO
            std::cout << m_pName << ": default construct allocator" << std::endl;
    #endif
        }
        EASTL_CustomAllocator(const EASTL_CustomAllocator& x)
            : m_pName(x.m_pName),
              m_totalAmountOfBytesAllocated(x.m_totalAmountOfBytesAllocated) {
    #ifdef DEBUG_MACRO
            std::cout << m_pName << ": copy construct allocator" << std::endl;
    #endif
        }
        EASTL_CustomAllocator(const EASTL_CustomAllocator& x, const char* pName)
            : m_pName(pName),
              m_totalAmountOfBytesAllocated(x.m_totalAmountOfBytesAllocated) {
    #ifdef DEBUG_MACRO
            std::cout << m_pName << ": copy construct allocator" << std::endl;
    #endif
        }
    
        EASTL_CustomAllocator& operator=(const EASTL_CustomAllocator& x) {
    #ifdef DEBUG_MACRO
            std::cout << m_pName << ": copy assignment" << std::endl;
    #endif
            m_pName = x.m_pName;
            m_totalAmountOfBytesAllocated = x.m_totalAmountOfBytesAllocated;
            return *this;
        }
    
        void* allocate(size_t num_of_bytes, int flags = 0) {
            m_totalAmountOfBytesAllocated += num_of_bytes;
            void* p = ::new((char*)0, flags, 0, (char*)0,        0) char[num_of_bytes];
    #ifdef DEBUG_MACRO
            std::cout << m_pName << ": allocate " << num_of_bytes << " bytes" << " at: " << (void*) p << std::endl;
    #endif
            return p;
        }
        void* allocate(size_t num_of_bytes, size_t alignment, size_t offset, int flags = 0) {
            m_totalAmountOfBytesAllocated += num_of_bytes;
            void* p = ::new(alignment, offset, (char*)0, flags, 0, (char*)0,        0) char[num_of_bytes];
    #ifdef DEBUG_MACRO
            std::cout << m_pName << ": allocate " << num_of_bytes << " bytes" << " at: " << (void*) p << std::endl;
    #endif
            return p;
        }
        void  deallocate(void* p, size_t num_of_bytes) {
            m_totalAmountOfBytesAllocated -= num_of_bytes;
    #ifdef DEBUG_MACRO
            std::cout << m_pName << ": deallocate " << num_of_bytes << " bytes" << " at: " << (void*) p << std::endl;
    #endif
            delete[](char*)p;
        }
    
        const char* get_name() const {
            return m_pName;
        }
        void        set_name(const char* pName) {
            m_pName = pName;
        }
        size_t get_totalAmountOfBytesAllocated() const {
            return m_totalAmountOfBytesAllocated;
        }
    
    protected:
        const char* m_pName;    // Debug name, used to track memory.
        size_t m_totalAmountOfBytesAllocated;   // keeps track of the memory currently allocated
    };
    
    
    bool operator==(const EASTL_CustomAllocator& a, const EASTL_CustomAllocator& b) {
        if (&a == &b) {
            return true;    // allocator a and b are equal if they are the same
        }
        else {
            return false;   // otherwhise, return false, because the state m_totalAmountOfBytesAllocated needs to be increased/decreased on splice and swap
        }
    }
    bool operator!=(const EASTL_CustomAllocator& a, const EASTL_CustomAllocator& b) {
        return false;
    }
    
    
    #endif /* EASTL_CUSTOM_ALLOCATOR_H_ */
    

    Pass that custom allocator type as a template parameter to a eastl container like following (also you can set a instance with a user-defined name at construction and even later by set_allocator()):

    eastl::list<int, EASTL_CustomAllocator> 
    list(EASTL_CustomAllocator("EASTL Some Name"));
    

    But I'm not sure how the debugging functionality is intended to be used.

    0 讨论(0)
提交回复
热议问题