dimanche 3 mars 2019

Crash when try to write a custom allocate_shared allocator and make it thread_local

My program has several type of small objects to be created and destroyed very frequently in each thread using make_shared, and the shared_ptr will not be passed to another thread, in which case, I decide to write a custom allocate_shared allocator with a boost::pool as its member to allocate fixed size of memory according to the type.

My code is as follows:

ObjectAllocator.h:

#include <boost/pool/pool.hpp>

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

    auto static constexpr block_size=64+sizeof(value_type);

public:
    ObjectAllocator() noexcept:pool_(block_size){}
    ObjectAllocator(const ObjectAllocator &other) noexcept :pool_(block_size){}
    ~ObjectAllocator()=default;

    template<typename U>
    ObjectAllocator(const ObjectAllocator<U> &other) noexcept :pool_(block_size){}

    template<typename U>
    ObjectAllocator& operator= (const ObjectAllocator<U> &other){
        return *this;
    }

    ObjectAllocator<T>& operator = (const ObjectAllocator &other){
        return *this;
    }

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

    T *allocate(size_type n, const void *hint=nullptr){
#ifdef _DEBUG
        assert(n==1);
#endif
        return static_cast<T*>(pool_.malloc());
    }

    void deallocate(T *ptr, size_type n){
#ifdef _DEBUG
        assert(n==1);
#endif
        pool_.free(ptr);
    }

private:
    boost::pool<> ObjectAllocator<T>::pool_(block_size);
}

template<typename T, typename U>
inline bool operator == (const ObjectAllocator<T>&, const ObjectAllocator<U>&){
    return true;
}

template<typename T, typename U>
inline bool operator != (const ObjectAllocator<T>& a, const ObjectAllocator<U> &b){
    return !(a==b);
}


namespace Allocator {
template <typename T>
thread_local ObjectAllocator<T> allocator;
}

main.cpp:

class ObjectA{
public:
    int s=0;
    void func(){
        std::cout<<s<<std::endl;
    }
    ObjectA() {//std::cout<<"()"<<std::endl;}
    ~ObjectA() {//std::cout<<"~"<<std::endl;}
};

std::vector<std::shared_ptr<ObjectA>> vec;
void test(){
    static uint32_t loop_count=1000*1000;
    for(uint32_t i=0;i<loop_count;i++){
         shared_ptr<ObjectA> packet = allocate_shared<ObjectA, ObjectAllocator<ObjectA>>(Allocator::allocator<ObjectA>);
         vec.push_back(packet);
    }
    vec.clear();
}

int main() {
    std::thread thread1(test);
    test();
    return 0;
}

When I try to test it, it crashs and I have no idea why. Could anyone helps to make it correct? Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire