Skip to content

Commit

Permalink
Finish release 0.5-1
Browse files Browse the repository at this point in the history
  • Loading branch information
foonathan committed Mar 18, 2016
2 parents d8253e5 + 0ee56fa commit d3ee8f8
Show file tree
Hide file tree
Showing 28 changed files with 1,275 additions and 1,246 deletions.
6 changes: 3 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "cmake/comp"]
path = cmake/comp
url = https://github.com/foonathan/compatibility.git
branch = git-submodule
path = cmake/comp
url = https://github.com/foonathan/compatibility.git
branch = git-submodule
2 changes: 2 additions & 0 deletions cmake/configuration.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ else()
endif()

# other options
option(FOONATHAN_MEMORY_CHECK_ALLOCATION_SIZE
"whether or not the size of the allocation will be checked" ON)
set(FOONATHAN_MEMORY_DEFAULT_ALLOCATOR heap_allocator CACHE STRING
"the default implementation allocator for higher-level ones")
option(FOONATHAN_MEMORY_THREAD_SAFE_REFERENCE
Expand Down
5 changes: 5 additions & 0 deletions include/foonathan/memory/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
/// \ingroup memory core
#define FOONATHAN_MEMORY_VERSION (FOONATHAN_MEMORY_VERSION_MAJOR * 100 + FOONATHAN_MEMORY_VERSION_MINOR)

/// Whether or not the allocation size will be checked,
/// i.e. the \ref bad_allocation_size thrown.
/// \ingroup memory core
#define FOONATHAN_MEMORY_CHECK_ALLOCATION_SIZE 1

/// Whether or not the \ref foonathan::memory::default_mutex will be \c std::mutex or \ref foonathan::memory::no_mutex.
/// \ingroup memory core
#define FOONATHAN_MEMORY_THREAD_SAFE_REFERENCE 1
Expand Down
11 changes: 10 additions & 1 deletion include/foonathan/memory/detail/align.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
#ifndef FOONATHAN_MEMORY_DETAIL_ALIGN_HPP_INCLUDED
#define FOONATHAN_MEMORY_DETAIL_ALIGN_HPP_INCLUDED

#include <cstdint>

#include <foonathan/alignas.hpp>
#include <foonathan/alignof.hpp>
#include <foonathan/max_align_t.hpp>

#include "../config.hpp"
#include "assert.hpp"

namespace foonathan { namespace memory
{
Expand All @@ -23,7 +26,13 @@ namespace foonathan { namespace memory

// returns the offset needed to align ptr for given alignment
// alignment must be valid
std::size_t align_offset(void *ptr, std::size_t alignment) FOONATHAN_NOEXCEPT;
inline std::size_t align_offset(void *ptr, std::size_t alignment) FOONATHAN_NOEXCEPT
{
FOONATHAN_MEMORY_ASSERT(is_valid_alignment(alignment));
auto address = reinterpret_cast<std::uintptr_t>(ptr);
auto misaligned = address & (alignment - 1);
return misaligned != 0 ? (alignment - misaligned) : 0;
}

// whether or not the pointer is aligned for given alignment
// alignment must be valid
Expand Down
8 changes: 5 additions & 3 deletions include/foonathan/memory/detail/assert.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#ifndef FOONATHAN_MEMORY_DETAIL_ASSERT_HPP_INCLUDED
#define FOONATHAN_MEMORY_DETAIL_ASSERT_HPP_INCLUDED

#include <cstdlib>

#include "../config.hpp"

namespace foonathan { namespace memory
Expand All @@ -29,9 +31,9 @@ namespace foonathan { namespace memory
#define FOONATHAN_MEMORY_UNREACHABLE(Msg) \
detail::handle_failed_assert("Unreachable code reached: " Msg, __FILE__, __LINE__, __func__)
#elif !defined(FOONATHAN_MEMORY_ASSERT)
#define FOONATHAN_MEMORY_ASSERT(Expr) static_cast<void>(Expr)
#define FOONATHAN_MEMORY_ASSERT_MSG(Expr, Msg) static_cast<void>(Expr)
#define FOONATHAN_MEMORY_UNREACHABLE(Msg) /* nothing */
#define FOONATHAN_MEMORY_ASSERT(Expr)
#define FOONATHAN_MEMORY_ASSERT_MSG(Expr, Msg)
#define FOONATHAN_MEMORY_UNREACHABLE(Msg) std::abort()
#endif
} // namespace detail
}} // namespace foonathan::memory
Expand Down
21 changes: 21 additions & 0 deletions include/foonathan/memory/detail/debug_helpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ namespace foonathan { namespace memory
FOONATHAN_CONSTEXPR std::size_t debug_fence_size
= FOONATHAN_MEMORY_DEBUG_FILL ? FOONATHAN_MEMORY_DEBUG_FENCE : 0u;

#if FOONATHAN_MEMORY_DEBUG_FILL
// fills size bytes of memory with debug_magic
void debug_fill(void *memory, std::size_t size, debug_magic m) FOONATHAN_NOEXCEPT;

Expand All @@ -41,6 +42,26 @@ namespace foonathan { namespace memory

// fills internal memory
void debug_fill_internal(void *memory, std::size_t size, bool free) FOONATHAN_NOEXCEPT;
#else
inline void debug_fill(void *, std::size_t, debug_magic) FOONATHAN_NOEXCEPT {}

inline void* debug_is_filled(void *, std::size_t, debug_magic) FOONATHAN_NOEXCEPT
{
return nullptr;
}

inline void* debug_fill_new(void *memory, std::size_t, std::size_t) FOONATHAN_NOEXCEPT
{
return memory;
}

inline void* debug_fill_free(void *memory, std::size_t, std::size_t) FOONATHAN_NOEXCEPT
{
return static_cast<char*>(memory);
}

inline void debug_fill_internal(void *, std::size_t, bool) FOONATHAN_NOEXCEPT {}
#endif

void debug_handle_invalid_ptr(const allocator_info &info, void *ptr);

Expand Down
219 changes: 45 additions & 174 deletions include/foonathan/memory/detail/free_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define FOONATHAN_MEMORY_DETAILL_FREE_LIST_HPP_INCLUDED

#include <cstddef>
#include <cstdint>

#include "align.hpp"
#include "utility.hpp"
Expand Down Expand Up @@ -51,7 +52,7 @@ namespace foonathan { namespace memory
// pre: !empty()
void* allocate() FOONATHAN_NOEXCEPT;

// returns a memory block big enough for n bytes (!, not nodes)
// returns a memory block big enough for n bytes
// might fail even if capacity is sufficient
void* allocate(std::size_t n) FOONATHAN_NOEXCEPT;

Expand All @@ -62,116 +63,30 @@ namespace foonathan { namespace memory
void deallocate(void *ptr, std::size_t n) FOONATHAN_NOEXCEPT;

//=== getter ===//
std::size_t node_size() const FOONATHAN_NOEXCEPT;
std::size_t node_size() const FOONATHAN_NOEXCEPT
{
return node_size_;
}

// alignment of all nodes
std::size_t alignment() const FOONATHAN_NOEXCEPT;

// number of nodes remaining
std::size_t capacity() const FOONATHAN_NOEXCEPT
{
return capacity_;
}

bool empty() const FOONATHAN_NOEXCEPT;

// alignment of all nodes
std::size_t alignment() const FOONATHAN_NOEXCEPT;
bool empty() const FOONATHAN_NOEXCEPT
{
return first_ == nullptr;
}

private:
// cache for new nodes that were never used
// it works like a stack and is continous, so supports arrays
class cache
{
public:
cache() FOONATHAN_NOEXCEPT
: cur_(nullptr), end_(nullptr) {}

cache(void *memory, std::size_t size) FOONATHAN_NOEXCEPT
: cur_(static_cast<char*>(memory)), end_(cur_ + size) {}

cache(cache &&other) FOONATHAN_NOEXCEPT
: cur_(other.cur_), end_(other.end_)
{
other.cur_ = other.end_ = nullptr;
}

~cache() FOONATHAN_NOEXCEPT = default;

cache& operator=(cache &&other) FOONATHAN_NOEXCEPT
{
cur_ = other.cur_;
end_ = other.end_;
other.cur_ = other.end_ = nullptr;
return *this;
}

// allocates memory of given size and alignment
// takes care of debug filling
// returns nullptr if no memory available
void* allocate(std::size_t size, std::size_t alignment) FOONATHAN_NOEXCEPT;

// tries to deallocate memory
// only works if deallocation in reversed order
// returns true if succesfully deallocated
bool try_deallocate(void *ptr, std::size_t size, std::size_t alignment) FOONATHAN_NOEXCEPT;

char* top() FOONATHAN_NOEXCEPT
{
return cur_;
}

char* end() FOONATHAN_NOEXCEPT
{
return end_;
}

// number of nodes that can be allocated from the cache
std::size_t no_nodes(std::size_t node_size) const FOONATHAN_NOEXCEPT;

private:
char *cur_, *end_;
};

// intrusive list for unused memory nodes
// gives only a stack like interface
class list_impl
{
public:
list_impl() FOONATHAN_NOEXCEPT
: first_(nullptr) {}

list_impl(list_impl &&other) FOONATHAN_NOEXCEPT
: first_(other.first_)
{
other.first_ = nullptr;
}

~list_impl() FOONATHAN_NOEXCEPT = default;

list_impl& operator=(list_impl &&other) FOONATHAN_NOEXCEPT
{
first_ = other.first_;
other.first_ = nullptr;
return *this;
}

// inserts all memory from an intervall into the list
// it will be inserted into the front
std::size_t insert(char *begin, char *end, std::size_t node_size) FOONATHAN_NOEXCEPT;

// pushes a single node into the list
// it takes care of debug filling
void push(void *ptr, std::size_t node_size) FOONATHAN_NOEXCEPT;

// pops the first node from the list
// it takes care of debug fillilng
// returns nullptr if empty
void* pop(std::size_t node_size) FOONATHAN_NOEXCEPT;

private:
char *first_;
};

cache cache_;
list_impl list_;
std::size_t fence_size() const FOONATHAN_NOEXCEPT;
void insert_impl(void *mem, std::size_t size) FOONATHAN_NOEXCEPT;

char *first_;
std::size_t node_size_, capacity_;
};

Expand All @@ -189,14 +104,23 @@ namespace foonathan { namespace memory
//=== constructor ===//
ordered_free_memory_list(std::size_t node_size) FOONATHAN_NOEXCEPT;

// calls other constructor plus insert
ordered_free_memory_list(std::size_t node_size,
void *mem, std::size_t size) FOONATHAN_NOEXCEPT;
void *mem, std::size_t size) FOONATHAN_NOEXCEPT
: ordered_free_memory_list(node_size)
{
insert(mem, size);
}

ordered_free_memory_list(ordered_free_memory_list &&other) FOONATHAN_NOEXCEPT;

~ordered_free_memory_list() FOONATHAN_NOEXCEPT = default;

ordered_free_memory_list& operator=(ordered_free_memory_list &&other) FOONATHAN_NOEXCEPT;
ordered_free_memory_list& operator=(ordered_free_memory_list &&other) FOONATHAN_NOEXCEPT
{
ordered_free_memory_list tmp(detail::move(other));
swap(*this, tmp);
return *this;
}

friend void swap(ordered_free_memory_list &a, ordered_free_memory_list &b) FOONATHAN_NOEXCEPT;

Expand All @@ -222,7 +146,13 @@ namespace foonathan { namespace memory
void deallocate(void *ptr, std::size_t n) FOONATHAN_NOEXCEPT;

//=== getter ===//
std::size_t node_size() const FOONATHAN_NOEXCEPT;
std::size_t node_size() const FOONATHAN_NOEXCEPT
{
return node_size_;
}

// alignment of all nodes
std::size_t alignment() const FOONATHAN_NOEXCEPT;

// number of nodes remaining
std::size_t capacity() const FOONATHAN_NOEXCEPT
Expand All @@ -232,80 +162,21 @@ namespace foonathan { namespace memory

bool empty() const FOONATHAN_NOEXCEPT
{
return list_.empty();
return capacity_ == 0u;
}

// alignment of all nodes
std::size_t alignment() const FOONATHAN_NOEXCEPT;

private:
// node size with fence
std::size_t node_fence_size() const FOONATHAN_NOEXCEPT;
std::size_t fence_size() const FOONATHAN_NOEXCEPT;

// xor linked list storing the free nodes
// keeps the list ordered to support arrays
class list_impl
{
public:
list_impl() FOONATHAN_NOEXCEPT
: first_(nullptr), last_(nullptr),
insert_(nullptr), insert_prev_(nullptr) {}

list_impl(std::size_t node_size,
void *memory, std::size_t no_nodes) FOONATHAN_NOEXCEPT
: list_impl()
{
insert(node_size, memory, no_nodes, false);
}

list_impl(list_impl &&other) FOONATHAN_NOEXCEPT
: first_(other.first_), last_(other.last_),
insert_(other.insert_), insert_prev_(other.insert_prev_)
{
other.first_ = other.last_ = nullptr;
other.insert_ = other.insert_prev_ = nullptr;
}

~list_impl() FOONATHAN_NOEXCEPT = default;

list_impl& operator=(list_impl &&other) FOONATHAN_NOEXCEPT
{
list_impl tmp(detail::move(other));
swap(*this, tmp);
return *this;
}

friend void swap(list_impl &a, list_impl &b) FOONATHAN_NOEXCEPT
{
detail::adl_swap(a.first_, b.first_);
detail::adl_swap(a.last_, b.last_);
detail::adl_swap(a.insert_, b.insert_);
detail::adl_swap(a.insert_prev_, b.insert_prev_);
}

// inserts nodes into the list
// node_size is the node_size_ member of the actual free list class
void insert(std::size_t node_size,
void* memory, std::size_t no_nodes, bool new_memory) FOONATHAN_NOEXCEPT;

// erases nodes from the list
// node_size is the node_size_ member of the actual free list class
void* erase(std::size_t node_size) FOONATHAN_NOEXCEPT;
void* erase(std::size_t node_size, std::size_t bytes_needed) FOONATHAN_NOEXCEPT;

bool empty() const FOONATHAN_NOEXCEPT;

private:
struct pos {char *prev, *after;};

// finds the position to insert memory
pos find_pos(std::size_t node_size, char* memory) const FOONATHAN_NOEXCEPT;

char *first_, *last_;
char *insert_, *insert_prev_; // pointer to last insert position
} list_;
// returns previous pointer
char* insert_impl(void *mem, std::size_t size) FOONATHAN_NOEXCEPT;

char* begin_node() FOONATHAN_NOEXCEPT;
char* end_node() FOONATHAN_NOEXCEPT;

std::uintptr_t begin_proxy_, end_proxy_;
std::size_t node_size_, capacity_;
char *last_dealloc_, *last_dealloc_prev_;
};

#if FOONATHAN_MEMORY_DEBUG_DOUBLE_DEALLOC_CHECk
Expand Down
Loading

0 comments on commit d3ee8f8

Please sign in to comment.