<commit_before>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011-2013                                                    *
 * <NAME> <<EMAIL>>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation; either version 2.1 of the License,               *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/


#ifndef CPPA_MEMORY_HPP
#define CPPA_MEMORY_HPP

#include <new>
#include <vector>
#include <memory>
#include <utility>
#include <typeinfo>
#include <iostream>

#include "cppa/config.hpp"
#include "cppa/ref_counted.hpp"

namespace cppa { class mailbox_element; }

namespace cppa { namespace detail {

namespace {

constexpr size_t s_alloc_size = 1024;  // allocate ~1kb chunks
constexpr size_t s_cache_size = 10240; // cache about 10kb per thread

} // namespace <anonymous>

class instance_wrapper {

 public:

    virtual ~instance_wrapper();

    // calls the destructor
    virtual void destroy() = 0;

    // releases memory
    virtual void deallocate() = 0;

};

class memory_cache {

 public:

    virtual ~memory_cache();

    // calls dtor and either releases memory or re-uses it later
    virtual void release_instance(void*) = 0;

    virtual std::pair<instance_wrapper*,void*> new_instance() = 0;

    // casts @p ptr to the derived type and returns it
    virtual void* downcast(memory_managed* ptr) = 0;

};

template<typename T>
class basic_memory_cache : public memory_cache {

    struct wrapper : instance_wrapper {
        ref_counted* parent;
        union { T instance; };
        wrapper() : parent(nullptr) { }
        ~wrapper() { }
        void destroy() { instance.~T(); }
        void deallocate() { parent->deref(); }
    };

    class storage : public ref_counted {

     public:

        storage() {
            for (auto& elem : data) {
                // each instance has a reference to its parent
                elem.parent = this;
                ref(); // deref() is called in wrapper::deallocate
            }
        }

        typedef wrapper* iterator;

        iterator begin() { return data; }

        iterator end() { return begin() + (s_alloc_size / sizeof(T)); }

     private:

        wrapper data[s_alloc_size / sizeof(T)];

    };

 public:

    std::vector<wrapper*> cached_elements;

    basic_memory_cache() {
        cached_elements.reserve(s_cache_size / sizeof(T));
    }

    ~basic_memory_cache() {
        for (auto e : cached_elements) e->deallocate();
    }

    void* downcast(memory_managed* ptr) {
        return static_cast<T*>(ptr);
    }


    virtual void release_instance(void* vptr) {
        CPPA_REQUIRE(vptr != nullptr);
        auto ptr = reinterpret_cast<T*>(vptr);<commit_msg>fixed nasty bug w/ large actor classes, fixes #88<commit_after>/******************************************************************************\
 *           ___        __                                                    *
 *          /\_ \    __/\ \                                                   *
 *          \//\ \  /\_\ \ \____    ___   _____   _____      __               *
 *            \ \ \ \/\ \ \ '__`\  /'___\/\ '__`\/\ '__`\  /'__`\             *
 *             \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_           *
 *             /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\          *
 *             \/____/ \/_/\/___/  \/____/ \ \ \/  \ \ \/  \/__/\/_/          *
 *                                          \ \_\   \ \_\                     *
 *                                           \/_/    \/_/                     *
 *                                                                            *
 * Copyright (C) 2011-2013                                                    *
 * <NAME> <<EMAIL>>                     *
 *                                                                            *
 * This file is part of libcppa.                                              *
 * libcppa is free software: you can redistribute it and/or modify it under   *
 * the terms of the GNU Lesser General Public License as published by the     *
 * Free Software Foundation; either version 2.1 of the License,               *
 * or (at your option) any later version.                                     *
 *                                                                            *
 * libcppa is distributed in the hope that it will be useful,                 *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       *
 * See the GNU Lesser General Public License for more details.                *
 *                                                                            *
 * You should have received a copy of the GNU Lesser General Public License   *
 * along with libcppa. If not, see <http://www.gnu.org/licenses/>.            *
\******************************************************************************/


#ifndef CPPA_MEMORY_HPP
#define CPPA_MEMORY_HPP

#include <new>
#include <vector>
#include <memory>
#include <utility>
#include <typeinfo>
#include <iostream>

#include "cppa/config.hpp"
#include "cppa/ref_counted.hpp"

namespace cppa { class mailbox_element; }

namespace cppa { namespace detail {

namespace {

constexpr size_t s_alloc_size = 1024;  // allocate ~1kb chunks
constexpr size_t s_min_elements = 5;   // don't create less than 5 elements
constexpr size_t s_cache_size = 10240; // cache about 10kb per thread

} // namespace <anonymous>

class instance_wrapper {

 public:

    virtual ~instance_wrapper();

    // calls the destructor
    virtual void destroy() = 0;

    // releases memory
    virtual void deallocate() = 0;

};

class memory_cache {

 public:

    virtual ~memory_cache();

    // calls dtor and either releases memory or re-uses it later
    virtual void release_instance(void*) = 0;

    virtual std::pair<instance_wrapper*,void*> new_instance() = 0;

    // casts @p ptr to the derived type and returns it
    virtual void* downcast(memory_managed* ptr) = 0;

};

template<typename T>
class basic_memory_cache : public memory_cache {

    struct wrapper : instance_wrapper {
        ref_counted* parent;
        union { T instance; };
        wrapper() : parent(nullptr) { }
        ~wrapper() { }
        void destroy() { instance.~T(); }
        void deallocate() { parent->deref(); }
    };

    class storage : public ref_counted {

        static constexpr size_t ne = s_alloc_size / sizeof(T);
        static constexpr size_t dsize = ne > s_min_elements ? ne : s_min_elements;

     public:

        storage() {
            for (auto& elem : data) {
                // each instance has a reference to its parent
                elem.parent = this;
                ref(); // deref() is called in wrapper::deallocate
            }
        }

        typedef wrapper* iterator;

        iterator begin() { return data; }

        iterator end() { return begin() + dsize; }

     private:

        wrapper data[dsize];

    };

 public:

    std::vector<wrapper*> cached_elements;

    basic_memory_cache() {
        cached_elements.reserve(s_cache_size / sizeof(T));
    }

    ~basic_memory_cache() {
        for (auto e : cached_elements) e->deallocate();
    }

    void* downcast(memory_managed* ptr) {
        return static_cast<T*>(ptr);
    }


    virtual void release_instance(void* vptr) {
        CPPA_REQUIRE(vptr != nullptr);
        auto ptr = reinterpret_cast<T*>(vptr);
{'fraction_non_alphanumeric': 0.14003628989219769, 'fraction_numerical': 0.006190628669014836, 'mean_word_length': 1.3273720814704422, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 40, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 52, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5863048', 'n_tokens_mistral': 2478, 'n_tokens_neox': 2310, 'n_words': 649}