xaizek / zograscope (License: AGPLv3 only) (since 2018-12-07)
Mainly a syntax-aware diff that also provides a number of additional tools.
<root> / third-party / pmr / monolithic.hpp (a7d1cc6c0f69eccec2cf815d7111eed479bfc56d) (2,643B) (mode 100644) [raw]
/* Copyright 2017 xaizek.
 *
 * Distributed under the Boost Software License, Version 1.0.
 *    (See accompanying file LICENSE_1_0.txt or copy at
 *          http://www.boost.org/LICENSE_1_0.txt)
 */

#ifndef PMR_MONOLITHIC_HPP_
#define PMR_MONOLITHIC_HPP_

#include "pmr_vector.hpp"
#include "polymorphic_allocator.hpp"

namespace cpp17 {

using namespace std;

namespace pmr {

class monolithic final : public memory_resource
{
    enum {
        blockSize = 64*1024,
        alignment = alignof(std::max_align_t),
    };

public:
    explicit monolithic(memory_resource *parent = get_default_resource());
    virtual ~monolithic() override;

protected:
    virtual void * do_allocate(size_t bytes, size_t alignment) override;
    virtual void do_deallocate(void *p, size_t bytes,
                               size_t alignment) override;
    virtual bool do_is_equal(const memory_resource &other)
        const noexcept override;

private:
    struct Block {
        size_t size;
        byte *start;
        byte *next;

        byte * aligned(size_t alignment) const;
        byte * allocate(size_t n, size_t alignment);
    };

    memory_resource *parent;
    vector<Block> blocks;
};

inline byte *
monolithic::Block::aligned(size_t alignment) const
{
    const size_t mod = reinterpret_cast<uintptr_t>(next)&(alignment - 1U);
    return (mod == 0U ? next : next + alignment - mod);
}

inline byte *
monolithic::Block::allocate(size_t n, size_t alignment)
{
    byte *ret = aligned(alignment);
    if (ret > start + size || static_cast<size_t>(start + size - ret) < n) {
        return nullptr;
    }

    next = ret + n;
    return ret;
}

inline
monolithic::monolithic(memory_resource *parent) : parent(parent), blocks(parent)
{ }

inline
monolithic::~monolithic()
{
    for (Block &alloc_rec : blocks) {
        parent->deallocate(alloc_rec.start, alloc_rec.size, alignment);
    }
}

inline void *
monolithic::do_allocate(size_t bytes, size_t align)
{
    void *ret;
    if (blocks.empty() || !(ret = blocks.back().allocate(bytes, align))) {
        const size_t size = max(static_cast<std::size_t>(blockSize), bytes);

        byte *r = static_cast<byte *>(parent->allocate(size, alignment));
        blocks.push_back(Block{size, r, r});
        ret = blocks.back().allocate(bytes, align);
    }

    return ret;
}

inline void
monolithic::do_deallocate(void */*p*/, size_t /*bytes*/, size_t /*alignment*/)
{
    // Do nothing.
}

inline bool
monolithic::do_is_equal(const memory_resource &other) const noexcept
{
    return this == &other;
}

} // close namespace pmr

} // close namespace cpp17

#endif // PMR_MONOLITHIC_HPP_
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/zograscope

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/zograscope

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master