Skip to content

Commit

Permalink
Refactoring: GC is now owned by the MM. Closes #81, Fixes #80
Browse files Browse the repository at this point in the history
  • Loading branch information
m4drat committed Mar 11, 2023
1 parent 4ee4c40 commit aec6c38
Show file tree
Hide file tree
Showing 16 changed files with 285 additions and 226 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ C++ memory allocator with smart features, such as garbage collection, and heap c
## 🔢 Current version

Current library version: 0.3.5
Warning: the API is not stable!

## 🔬 Features

Expand All @@ -42,7 +43,6 @@ Current library version: 0.3.5
- All Unix-like systems (where it is possible to use `mmap`)
- g++ or clang++ compilers
- __Currently supports only single-threaded applications__
- Currently, you can't use manual memory management and GarbageCollection simultaneously (e.g. you should only use smart pointers, or manually control memory using Allocate and Deallocate)

## ❓ Usage

Expand Down Expand Up @@ -122,7 +122,7 @@ Library options:

## 🔳 Environment options

- `MPP_DUMP_OBJECTS_GRAPH=1` / `MPP_DUMP_OBJECTS_GRAPH=2` - dump objects graph to file `objects.dot`, while performing `GC::Collect()` (only possible in debug mode)
- `MPP_DUMP_OBJECTS_GRAPH=1` / `MPP_DUMP_OBJECTS_GRAPH=2` - dump objects graph to file `objects.dot`, while performing `CollectGarbage()` (only possible in debug mode)

- `MPP_SHOW_STATISTICS=1` - display statistics after program termination (should be built with `MPP_STATS` set to ON)

Expand All @@ -144,7 +144,7 @@ Library options:
...

// collect all garbage + compact memory (should be called manually)
GC::GetInstance().Collect();
mpp::CollectGarbage();
```

- ~~Manual memory management~~ - deprecated
Expand Down Expand Up @@ -327,7 +327,7 @@ Memplusplus provides different debug-like features, such as data visualizers, pr
treeNode5->left = nullptr;
treeNode5->right = nullptr;

GC::GetInstance().Collect();
CollectGarbage();
```

Executing this code with `MPP_DUMP_OBJECTS_GRAPH=1` will generate this graph:
Expand Down
8 changes: 4 additions & 4 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#!/bin/bash

CXX=clang++-15 cmake -S . -B build \
CXX=g++ cmake -S . -B build \
-DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE \
-DCMAKE_BUILD_TYPE=Debug \
-DMPP_BUILD_FUZZER=ON \
-DMPP_BUILD_FUZZER=OFF \
-DMPP_BUILD_EXAMPLE=ON \
-DMPP_BUILD_TESTS=ON \
-DMPP_BUILD_DOCS=OFF \
-DMPP_SANITIZERS=ON \
-DMPP_SANITIZERS=OFF \
-DMPP_BUILD_SHARED_LIBS=OFF \
-DMPP_FULL_DEBUG=ON \
-DMPP_SECURE=ON \
-DMPP_PROFILE=ON \
-DMPP_COLOUR=ON \
-DMPP_STATS=ON

CXX=clang++-15 cmake --build build --config Debug --target all -- -j 16
CXX=g++ cmake --build build --config Debug --target all -- -j 16
4 changes: 2 additions & 2 deletions example_project/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Worker
}

if constexpr (DoLayout) {
GC::GetInstance().Collect();
CollectGarbage();
}
}

Expand All @@ -59,7 +59,7 @@ class Worker

// return current->data;

mpp::utils::ErrorAbort("TEST!\n");
// mpp::utils::ErrorAbort("TEST!\n");

SharedGcPtr<ListNode>* current = &m_LinkedListHead;

Expand Down
1 change: 0 additions & 1 deletion libmemplusplus/include/mpplib/containers/gc_graph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#include <vector>

#include "mpplib/containers/vertex.hpp"
#include "mpplib/memory_manager.hpp"
#include "mpplib/utils/profiler_definitions.hpp"

namespace mpp {
Expand Down
17 changes: 3 additions & 14 deletions libmemplusplus/include/mpplib/gc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "mpplib/containers/gc_graph.hpp"
#include "mpplib/gcptr.hpp"
#include "mpplib/heuristics/heuristics.hpp"
#include "mpplib/memory_manager.hpp"
#include "mpplib/utils/profiler_definitions.hpp"

#if MPP_STATS == 1
Expand All @@ -28,7 +27,7 @@ namespace mpp {
/**
* @brief GarbageCollector class.
*/
class GC
class GarbageCollector
{
private:
/**
Expand All @@ -54,11 +53,11 @@ namespace mpp {
#endif

//! @brief Current cycle to dump objects graph
static uint32_t m_currentCycle;
uint32_t m_totalInvocations;

public:
//! @brief Construct a new GC object
GC();
GarbageCollector();

/**
* @brief Collect garbage.
Expand Down Expand Up @@ -105,15 +104,5 @@ namespace mpp {
{
m_activeGcPtrs.insert(t_ptr);
}

/**
* @brief Get the Instance of GC object
* @return GC& Global Garbage Collector
*/
static GC& GetInstance()
{
static GC gcInstance;
return gcInstance;
}
};
}
101 changes: 61 additions & 40 deletions libmemplusplus/include/mpplib/memory_manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "mpplib/arena.hpp"
#include "mpplib/chunk.hpp"
#include "mpplib/gc.hpp"
#include "mpplib/memory_manager.hpp"
#include "mpplib/utils/profiler_definitions.hpp"
#include <memory>
Expand All @@ -18,6 +19,7 @@
#include <type_traits>

namespace mpp {
// Forward declarations
class Arena;

template<class T>
Expand All @@ -37,24 +39,21 @@ namespace mpp {
template<class Type, class... Args>
friend SharedGcPtr<Type[]> MakeSharedN(uint32_t t_size, Args&&... t_args);

friend class GC;
friend class GarbageCollector;
friend class Arena;

/**
* @brief All existing arenas.
*/
//! @brief All existing arenas.
std::vector<std::unique_ptr<Arena>> m_arenaList;

/**
* @brief User specified hook to call before Allocate
*/
//! @brief User specified hook to call before Allocate.
std::function<void*(std::size_t)> m_allocateHook;

/**
* @brief User specified hook to call before Deallocate
*/
//! @brief User specified hook to call before Deallocate.
std::function<bool(void*)> m_deallocateHook;

//! @brief Garbage collector for this memory manager.
GarbageCollector m_gc;

/**
* @brief Generate MMAP hint.
* @return std::intptr_t base address for new page.
Expand All @@ -65,7 +64,7 @@ namespace mpp {
* @brief mmap(2) wrapper, that maps readble and writable, not shared
* memory page of given size.
* @throw NoMemoryException, if system cannot map new memory.
* @param t_size Size of mapped memory
* @param t_size Size of mapped memory.
* @return void* pointer to mapped memory.
*/
static std::byte* SysAlloc(std::size_t t_size);
Expand All @@ -75,7 +74,7 @@ namespace mpp {
* @param ptr is pointer to memory, that will be unmapped.
* @param pageSize size of memory, that will be unmapped.
* @throw UnmapMemoryException, if cannot unmap memory.
* @return true if everything is fine, otherwise it will throw exception
* @return true if everything is fine, otherwise it will throw exception.
*/
static bool SysDealloc(void* t_ptr, std::size_t t_pageSize);

Expand All @@ -98,15 +97,15 @@ namespace mpp {
/**
* @brief Finds suitable chunk of requested size from somwhere (top/freelist).
* @param t_realSize already aligned size of request.
* @return Chunk* allocated chunk, or nullptr
* @return Chunk* allocated chunk, or nullptr.
*/
Chunk* GetSuitableChunk(std::size_t t_realSize);

/**
* @brief Construct objects at t_objectPtr using params provided in t_args
* @param t_objectPtr pointer to memory location where to construct the object
* @param t_args arguments to T's constructor
* @return T* memory location where constructed object is stored
* @brief Construct objects at t_objectPtr using params provided in t_args.
* @param t_objectPtr pointer to memory location where to construct the object.
* @param t_args arguments to T's constructor.
* @return T* memory location where constructed object is stored.
*/
template<class T, class... Args>
static T* Construct(T* t_objectPtr, Args&&... t_args)
Expand All @@ -115,10 +114,10 @@ namespace mpp {
}

/**
* @brief Destroys single object
* @tparam T user parameter type
* @param t_objectPtr pointer to object
* @return T* pointer to the destroyed object
* @brief Destroys single object.
* @tparam T user parameter type.
* @param t_objectPtr pointer to object.
* @return T* pointer to the destroyed object.
*/
template<class T>
static inline T* DestroyObject(T* t_objectPtr)
Expand All @@ -131,11 +130,11 @@ namespace mpp {
}

/**
* @brief Destroys all objects inside array
* @tparam T user parameter type
* @param t_objectPtr pointer to the array start
* @param t_arraySize array size
* @return T* pointer to the array beginning
* @brief Destroys all objects inside array.
* @tparam T user parameter type.
* @param t_objectPtr pointer to the array start.
* @param t_arraySize array size.
* @return T* pointer to the array beginning.
*/
template<class T>
static T* DestroyArray(T* t_objectPtr, std::size_t t_arraySize)
Expand Down Expand Up @@ -169,46 +168,55 @@ namespace mpp {
/**
* @brief Ceils number (t_size) to the nearest number such that this number divided by
* t_alignment has no remainder.
* @param t_size is number to align
* @param t_alignment is alignment
* @return std::size_t Aligned number
* @param t_size is number to align.
* @param t_alignment is alignment.
* @return std::size_t Aligned number.
*/
static std::size_t Align(std::size_t t_size, int32_t t_alignment);

/**
* @brief Sets hook for Allocate method
* @param t_allocateHook std::function to set as hook
* @brief Sets on-allocate hook.
* @param t_allocateHook std::function to set as a hook.
*/
void SetAllocateHook(const std::function<void*(std::size_t)>& t_allocateHook);

/**
* @brief Sets hook for DeAllocate method
* @param t_deallocateHook std::function to set as hook
* @brief Sets on-deallocate hook.
* @param t_deallocateHook std::function to set as a hook.
*/
void SetDeallocateHook(const std::function<bool(void*)>& t_deallocateHook);

#if MPP_STATS == 1 || MPP_DEBUG == 1
/**
* @brief Visualizes heap layout.
* @param t_out output stream to write to.
* @return std::ostream& stream reference
* @return std::ostream& stream reference.
*/
std::ostream& VisHeapLayout(std::ostream& t_out, void* t_ptr);
#endif

/**
* @brief Get reference to vector of arenas.
* @return const std::vector<std::unique_ptr<Arena>>& to arenas
* @return const std::vector<std::unique_ptr<Arena>>& to arenas.
*/
std::vector<std::unique_ptr<Arena>>& GetArenaList()
{
return m_arenaList;
}

/**
* @brief Get reference to garbage collector.
* @return GarbageCollector& reference to garbage collector.
*/
GarbageCollector& GetGC() noexcept
{
return m_gc;
}

/**
* @brief Finds inside which arena t_ptr points.
* @param t_ptr heap pointer.
* @return std::unique_ptr<Arena>& if pointer points into arena, nullptr otherwise
* @return std::unique_ptr<Arena>& if pointer points into arena, nullptr otherwise.
*/
std::optional<std::reference_wrapper<std::unique_ptr<Arena>>> GetArenaByPtr(void* t_ptr);

Expand All @@ -217,7 +225,7 @@ namespace mpp {
* @brief Default Allocate method. Allocates chunk with size at least
* t_userDataSize.
* @param t_userDataSize request size.
* @return void* pointer to user data in allocated chunk
* @return void* pointer to user data in allocated chunk.
*/
void* Allocate(std::size_t t_userDataSize);

Expand All @@ -227,17 +235,23 @@ namespace mpp {
* @brief Deallocates chunk of memory.
* @param t_chunkPtr pointer to start of user data.
* @return true, if chunk was deallocated successfully, false if chunk
* doesn't belong to any arena
* doesn't belong to any arena.
*/
bool Deallocate(void* t_chunkPtr);

/**
* @brief Collects garbage from all arenas, by invoking GarbageCollector.Collect().
* @return true if garbage collection was successful, false otherwise.
*/
bool CollectGarbage();

/**
* @deprecated instead of using Allocate<T> use @sa MakeShared<T> / @sa MakeSharedN<T>
* @brief Template version of Allocate to call object constructor.
* @tparam T object to allocate type.
* @tparam Args list of arguments to pass to object constructor.
* @param t_args actual arguments to object constructor.
* @return T* constructed object
* @return T* constructed object.
*/
template<class T, class... Args>
T* Allocate(Args&&... t_args)
Expand All @@ -254,7 +268,7 @@ namespace mpp {
* @tparam T actual type of the object.
* @param t_objPtr pointer to object of type T.
* @return true, if chunk was deallocated successfully, false if chunk
* doesn't belong to any arena
* doesn't belong to any arena.
*/
template<class T>
bool Deallocate(T* t_objPtr)
Expand Down Expand Up @@ -371,4 +385,11 @@ namespace mpp {
* @return const std::vector<std::unique_ptr<Arena>>& to arenas
*/
std::vector<std::unique_ptr<Arena>>& GetArenaList();

/**
* @brief Wrapper around @sa MemoryManager::CollectGarbage. Essentially invokes garbage
* collection for all arenas.
* @return true if garbage collection was successful, false otherwise
*/
bool CollectGarbage();
}
Loading

0 comments on commit aec6c38

Please sign in to comment.