Skip to content

Commit

Permalink
+ added copyright information and licensce file
Browse files Browse the repository at this point in the history
+ added example
+ added README.md file
* fixed bug in free_memory_list::allocate(n), allows n to be 1 now
* improved memory_pool allocation for arrays if multiple elements can fit into one node
  • Loading branch information
foonathan committed Mar 29, 2015
1 parent 2b3570d commit 03d8347
Show file tree
Hide file tree
Showing 20 changed files with 262 additions and 13 deletions.
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>

This software is provided 'as-is', without any express or
implied warranty. In no event will the authors be held
liable for any damages arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute
it freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but
is not required.

2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software.

3. This notice may not be removed or altered from any
source distribution.
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
memory
======
This library provides various memory allocators for high-performance allocation and deallocation. These allocators are provided in the form of a new allocator concept: RawAllocator. A RawAllocator is an improved version over the classical STL-Allocator. There are various wrapper classes and traits to convert between the two types. Each RawAllocator has the following interface or an appropriate specialization of the raw_allocator_traits:

// A raw allocator, only supports raw memory allocation.
// Similar to ::operator new/malloc. This avoids the need to be templated and to use one allocator for multiple types.
// The raw_allocator_traits can be specialized to adopt to another interface.
class raw_allocator
{
public:
// Whether or not the allocator is stateful.
// Non-stateful allocators don't need to be stored and can be default constructed on the fly.
using is_stateful = std::true_type/std::false_type;
// The allocator is required to be moveable
raw_allocator(raw_allocator&&);
raw_allocator& operator=(raw_allocator&&);
// Allocates memory for a node. A node is a single object of given size and alignment.
// Precondition: size <= max_node_size() && alignment <= max_alignment()
// Throws an exception derived from std::bad_alloc in case of failure.
void* allocate_node(std::size_t size, std::size_t alignment);
// Allocates memory for an array of multiple nodes.
// Precondition: count * size <= max_array_size() && alignment <= max_alignment()
// Throws an exception derived from std::bad_alloc in case of failure.
void* allocate_array(std::size_t count, std::size_t size, std::size_t alignment);
// Deallocates memory for a node. Must not throw.
void deallocate_node(void *node, std::size_t size, std::size_t alignment) noexcept;
// Deallocates memory for an array of nodes. Must not throw.
void deallocate_array(void *array, std::size_t count, std::size_t size, std::size_t alignment) noexcept;
// Returns the maximum size of a node, inclusive. Should not throw.
std::size_t max_node_size() const;
// Returns the maximum size for an array (total size, no_elements * object_size), inclusive. Should not throw.
std::size_t max_array_size() const;
// Returns the maximum supported alignment, inclusive. Should not throw.
std::size_t max_alignment() const;
};
4 changes: 4 additions & 0 deletions allocator_adapter.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_ALLOCATOR_ADAPTER_HPP_INCLUDED
#define FOONATHAN_MEMORY_ALLOCATOR_ADAPTER_HPP_INCLUDED

Expand Down
6 changes: 5 additions & 1 deletion allocator_traits.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_ALLOCATOR_TRAITS_HPP_INCLUDED
#define FOONATHAN_MEMORY_ALLOCATOR_TRAITS_HPP_INCLUDED

Expand Down Expand Up @@ -141,4 +145,4 @@ namespace foonathan { namespace memory
{};
}} // namespace foonathan::memory

#endif // FOONATHAN_MEMORY_ALLOCATOR_TRAITS_HPP_INCLUDED
#endif // FOONATHAN_MEMORY_ALLOCATOR_TRAITS_HPP_INCLUDED
1 change: 1 addition & 0 deletions biicode.conf
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
# user/block # No version number means not published yet
# You can change it to publish to a different track, and change version, e.g.
# user/block(track): 7
foonathan/memory: 0

[paths]
# Local directories to look for headers (within block)
Expand Down
11 changes: 7 additions & 4 deletions detail/free_list.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ namespace
bool check_n(char* &cur, std::size_t n, std::size_t el_size) noexcept
{
--n; // we already have one (cur)
if (n == 0u)
return true;
for (; cur; cur += el_size)
{
if (next(cur) == cur + el_size)
Expand All @@ -66,11 +68,12 @@ namespace
}
}

constexpr std::size_t free_memory_list::min_element_size;
constexpr std::size_t free_memory_list::min_element_alignment;

free_memory_list::free_memory_list(std::size_t el_size) noexcept
: first_(nullptr), el_size_(el_size), capacity_(0u)
{
assert(el_size >= min_element_size && "element size too small");
}
: first_(nullptr), el_size_(std::max(min_element_size, el_size)), capacity_(0u)
{}

free_memory_list::free_memory_list(std::size_t el_size,
void *mem, std::size_t size) noexcept
Expand Down
120 changes: 116 additions & 4 deletions example/main.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,121 @@
#include "../pool.hpp"
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

using namespace foonathan::memory;
#include <iostream>
#include <unordered_set>
#include <vector>

int main()
#include "../allocator_adapter.hpp" // for raw_allocator_allocator
#include "../pool_allocator.hpp" // for memory_pool
#include "../tracking.hpp" // for make_tracked_allocator

using namespace foonathan;

// uses a RawAllocator or a class that has specialized the raw_allocator_traits
template <class RawAllocator>
void use_allocator(RawAllocator &alloc)
{
// raw_allocator_allocator is the bridge between RawAllocators and STL-Allocator
using std_allocator = memory::raw_allocator_allocator<int, RawAllocator>;

// create a vector that uses the pool
// it is passed via reference to the vector
std::vector<int, std_allocator> a(alloc);
// add some elements
std::clog << "vector creation\n";
for (auto i = 0u; i != 10u; ++i)
a.push_back(i);

// remove the third one
std::clog << "vector erase\n";
a.erase(a.begin() + 2);

// make a copy of the vector
// they share the same allocator
std::clog << "vector copy\n";
auto b = a;
// insert an element into the copy
std::clog << "vector insert\n";
b.push_back(4);

// move b into a new vector
// the allocator is transferred two to make it fast
std::clog << "vector move\n";
auto c = std::move(b);

// swap a and c, this also swaps the allocator
std::clog << "vector swap\n";
swap(a, c);

// create a set that uses the allocator
std::clog << "create set\n";
std::unordered_set<int, std::hash<int>, std::equal_to<int>, std_allocator>
set(5, {}, {}, alloc); // set bucket counter to trigger rehash

// insert and erase values
std::clog << "insert/erase set\n";
for (auto i = 0u; i != 10u; ++i)
set.insert(i);
set.erase(2);
set.erase(10);
}

int main()
{
memory_pool<> pool(16, 1024);
std::clog << std::unitbuf;
// a memory pool that supports arrays, each node is 32 bytes big, initially 4KB long
memory::memory_pool<memory::array_pool> pool(32, 4096);
{
// allocate one such node
auto mem = pool.allocate_node();
std::clog << "Allocated a node from pool " << mem << '\n';

// deallocate it
pool.deallocate_node(mem);

// allocate an array, that is, multiple nodes one after the other
mem = pool.allocate_array(16);
std::clog << "Allocated array from pool " << mem << '\n';
// deallocate it
pool.deallocate_array(mem, 16);
}
// use the allocator inside STL containers
std::clog << "\npool test\n\n";
use_allocator(pool);

// tracker class that logs internal behavior of the allocator
struct tracker
{
void on_node_allocation(void *mem, std::size_t size, std::size_t) noexcept
{
std::clog << this << " node allocated: ";
std::clog << mem << " (" << size << ") " << '\n';
}

void on_array_allocation(void *mem, std::size_t count, std::size_t size, std::size_t) noexcept
{
std::clog << this << " array allocated: ";
std::clog << mem << " (" << count << " * " << size << ") " << '\n';
}

void on_node_deallocation(void *ptr, std::size_t, std::size_t) noexcept
{
std::clog << this << " node deallocated: " << ptr << " \n";
}

void on_array_deallocation(void *ptr, std::size_t, std::size_t, std::size_t) noexcept
{
std::clog << this << " array deallocated: " << ptr << " \n";
}
};

// create a tracked memory_pool to see what kind of allocations are made
// necessary to move the pool into the new allocator, since it can't be copied
auto tracked_pool = memory::make_tracked_allocator(tracker{}, std::move(pool));
// tracked_pool does not provide the pool specific interface anymore, only the general one

// use it
std::clog << "\ntracked pool test\n\n";
use_allocator(tracked_pool);
}
4 changes: 4 additions & 0 deletions heap_allocator.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#include "heap_allocator.hpp"

#include <cassert>
Expand Down
4 changes: 4 additions & 0 deletions heap_allocator.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_HEAP_ALLOCATOR_HPP_INCLUDED
#define FOONATHAN_MEMORY_HEAP_ALLOCATOR_HPP_INCLUDED

Expand Down
4 changes: 4 additions & 0 deletions new_allocator.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#include "new_allocator.hpp"

using namespace foonathan::memory;
Expand Down
4 changes: 4 additions & 0 deletions new_allocator.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_NEW_ALLOCATOR_HPP_INCLUDED
#define FOONATHAN_MEMORY_NEW_ALLOCATOR_HPP_INCLUDED

Expand Down
19 changes: 16 additions & 3 deletions pool_allocator.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_POOL_ALLOCATOR_HPP_INCLUDED
#define FOONATHAN_MEMORY_POOL_ALLOCATOR_HPP_INCLUDED

Expand Down Expand Up @@ -178,7 +182,10 @@ namespace foonathan { namespace memory
assert(size <= max_node_size(state) && "invalid node size");
assert(alignment <= max_alignment(state) && "invalid alignment");
assert(count * size <= max_array_size(state) && "invalid array size");
return state.allocate_array(count);
if (size == max_node_size(state))
return state.allocate_array(count);
auto ratio = max_node_size(state) / size;
return state.allocate_array(count / ratio + 1);
}
/// @}

Expand All @@ -191,9 +198,15 @@ namespace foonathan { namespace memory
}

static void deallocate_array(allocator_type &state,
void *array, std::size_t count, std::size_t, std::size_t) noexcept
void *array, std::size_t count, std::size_t size, std::size_t) noexcept
{
state.deallocate_array(array, count);
if (size == max_node_size(state))
state.deallocate_array(array, count);
else
{
auto ratio = max_node_size(state) / size;
state.deallocate_array(array, count / ratio + 1);
}
}
/// @}

Expand Down
4 changes: 4 additions & 0 deletions pool_collection.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#include "pool_collection.hpp"

#include <cmath>
Expand Down
4 changes: 4 additions & 0 deletions pool_collection.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_POOL_COLLECTION_HPP_INCLUDED
#define FOONATHAN_MEMORY_POOL_COLLECTION_HPP_INCLUDED

Expand Down
4 changes: 4 additions & 0 deletions pool_type.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_POOL_TYPE_HPP_INCLUDED
#define FOONATHAN_MEMORY_POOL_TYPE_HPP_INCLUDED

Expand Down
4 changes: 4 additions & 0 deletions raw_allocator_base.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_RAW_ALLOCATOR_BASE
#define FOONATHAN_MEMORY_RAW_ALLOCATOR_BASE

Expand Down
6 changes: 5 additions & 1 deletion smart_ptr.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_SMART_PTR_HPP_INCLUDED
#define FOONATHAN_MEMORY_SMART_PTR_HPP_INCLUDED

Expand Down Expand Up @@ -243,4 +247,4 @@ namespace foonathan { namespace memory
}
}} // namespace foonathan::memory

#endif // FOONATHAN_MEMORY_SMART_PTR_HPP_INCLUDED
#endif // FOONATHAN_MEMORY_SMART_PTR_HPP_INCLUDED
4 changes: 4 additions & 0 deletions stack_allocator.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_STACK_ALLOCATOR_HPP_INCLUDED
#define FOONATHAN_MEMORY_STACK_ALLOCATOR_HPP_INCLUDED

Expand Down
4 changes: 4 additions & 0 deletions std_allocator_base.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_STD_ALLOCATOR_BASE_HPP_INCLUDED
#define FOONATHAN_MEMORY_STD_ALLOCATOR_BASE_HPP_INCLUDED

Expand Down
4 changes: 4 additions & 0 deletions tracking.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// Copyright (C) 2015 Jonathan Müller <jonathanmueller.dev@gmail.com>
// This file is subject to the license terms in the LICENSE file
// found in the top-level directory of this distribution.

#ifndef FOONATHAN_MEMORY_TRACKING_HPP_INCLUDED
#define FOONATHAN_MEMORY_TRACKING_HPP_INCLUDED

Expand Down

0 comments on commit 03d8347

Please sign in to comment.