Memory.h fixes

* Use a Nifty Counter for rpmalloc initialization. This fixes init order
  with other static objects using MmAllocator or MemoryManagger
* Fix exception throwing in AlignedAllocator
* Add missing constructor to MmAllocator for compatibility with std
  containers
This commit is contained in:
Lukas W
2018-04-15 21:45:30 +02:00
parent 3c73270c23
commit 1340c273c7
4 changed files with 120 additions and 41 deletions

View File

@@ -1,5 +1,5 @@
/*
* MemoryManager.h
* Memory.h
*
* Copyright (c) 2017 Lukas W <lukaswhl/at/gmail.com>
* Copyright (c) 2014 Simon Symeonidis <lethaljellybean/at/gmail/com>
@@ -32,25 +32,35 @@
#include <vector>
#include "lmms_export.h"
#include "NiftyCounter.h"
class LMMS_EXPORT MemoryManager
{
public:
struct ThreadGuard
{
ThreadGuard();
~ThreadGuard();
};
static void * alloc( size_t size );
static void free( void * ptr );
private:
static void initialize();
static void deinitialize();
static void thread_initialize();
static void thread_deinitialize();
public:
typedef NiftyCounter<MemoryManager::initialize, MemoryManager::deinitialize> MmCounter;
typedef NiftyCounterTL<MemoryManager::thread_initialize, MemoryManager::thread_deinitialize> ThreadGuard;
};
static MemoryManager::MmCounter _mm_counter;
template<typename T>
struct MmAllocator
class MmAllocator
{
public:
MmAllocator() = default;
template< class U > MmAllocator( const MmAllocator<U>& other ) {}
typedef T value_type;
template<class U> struct rebind { typedef MmAllocator<U> other; };
template<class U> struct rebind { typedef MmAllocator<U> other; };
T* allocate( std::size_t n )
{

60
include/NiftyCounter.h Normal file
View File

@@ -0,0 +1,60 @@
/*
* NiftyCounter.h
*
* Copyright (c) 2018 Lukas W <lukaswhl/at/gmail.com>
*
* This file is part of LMMS - https://lmms.io
*
* This file is licensed under the MIT license. See LICENSE.MIT.txt file in the
* project root for details.
*
*/
#pragma once
/// Nifty counter, also known as "Schwarz Counter". Used for ensuring global
/// static object initialization and destruction order.
template <typename T> class _NiftyCounter_Base
{
public:
_NiftyCounter_Base()
{
if (! T::inc()) T::init();
}
_NiftyCounter_Base(const _NiftyCounter_Base& other) : _NiftyCounter_Base() {}
~_NiftyCounter_Base()
{
if (! T::dec()) T::deinit();
}
};
template <typename T, void C(), void D()> class _NiftyCounterCD_Base : public _NiftyCounter_Base<T>
{
friend class _NiftyCounter_Base<T>;
private:
static void init() { C(); }
static void deinit() { D(); }
static int inc() { return T::s_count++; }
static int dec() { return T::s_count--; }
};
/// Pass construction and destruction functions as template arguments C and D.
template <void C(), void D()> class NiftyCounter : public _NiftyCounterCD_Base<NiftyCounter<C,D>, C,D>
{
friend class _NiftyCounterCD_Base<NiftyCounter<C,D>, C,D>;
private:
static int s_count;
};
template <void C(), void D()> int NiftyCounter<C, D>::s_count = 0;
/// Thread-local version of NiftyCounter
template <void C(), void D()> class NiftyCounterTL : public _NiftyCounterCD_Base<NiftyCounterTL<C,D>, C,D>
{
friend class _NiftyCounterCD_Base<NiftyCounterTL<C,D>, C,D>;
private:
thread_local static int s_count;
};
template <void C(), void D()> thread_local int NiftyCounterTL<C, D>::s_count = 0;