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:
18
LICENSE.MIT.txt
Normal file
18
LICENSE.MIT.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
The MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -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
60
include/NiftyCounter.h
Normal 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;
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* MemoryManager.cpp
|
||||
* Memory.cpp
|
||||
*
|
||||
* Copyright (c) 2017 Lukas W <lukaswhl/at/gmail.com>
|
||||
* Copyright (c) 2018 Lukas W <lukaswhl/at/gmail.com>
|
||||
* Copyright (c) 2014 Simon Symeonidis <lethaljellybean/at/gmail/com>
|
||||
* Copyright (c) 2004-2014 Tobias Doerffel <tobydox/at/users.sourceforge.net>
|
||||
*
|
||||
@@ -30,35 +30,6 @@
|
||||
#include <QtCore/QtGlobal>
|
||||
#include "rpmalloc.h"
|
||||
|
||||
/// Global static object handling rpmalloc intializing and finalizing
|
||||
struct MemoryManagerGlobalGuard {
|
||||
MemoryManagerGlobalGuard() {
|
||||
rpmalloc_initialize();
|
||||
}
|
||||
~MemoryManagerGlobalGuard() {
|
||||
rpmalloc_finalize();
|
||||
}
|
||||
} static mm_global_guard;
|
||||
|
||||
|
||||
namespace {
|
||||
static thread_local size_t thread_guard_depth;
|
||||
}
|
||||
|
||||
MemoryManager::ThreadGuard::ThreadGuard()
|
||||
{
|
||||
if (thread_guard_depth++ == 0) {
|
||||
rpmalloc_thread_initialize();
|
||||
}
|
||||
}
|
||||
|
||||
MemoryManager::ThreadGuard::~ThreadGuard()
|
||||
{
|
||||
if (--thread_guard_depth == 0) {
|
||||
rpmalloc_thread_finalize();
|
||||
}
|
||||
}
|
||||
|
||||
static thread_local MemoryManager::ThreadGuard local_mm_thread_guard{};
|
||||
|
||||
void* MemoryManager::alloc(size_t size)
|
||||
@@ -78,6 +49,26 @@ void MemoryManager::free(void * ptr)
|
||||
return rpfree(ptr);
|
||||
}
|
||||
|
||||
void MemoryManager::initialize()
|
||||
{
|
||||
rpmalloc_initialize();
|
||||
}
|
||||
|
||||
void MemoryManager::deinitialize()
|
||||
{
|
||||
rpmalloc_finalize();
|
||||
}
|
||||
|
||||
void MemoryManager::thread_initialize()
|
||||
{
|
||||
rpmalloc_thread_initialize();
|
||||
}
|
||||
|
||||
void MemoryManager::thread_deinitialize()
|
||||
{
|
||||
rpmalloc_thread_finalize();
|
||||
}
|
||||
|
||||
void* _AlignedAllocator_Base::alloc_impl( size_t n , size_t alignment)
|
||||
{
|
||||
char *ptr, *ptr2, *aligned_ptr;
|
||||
@@ -85,7 +76,7 @@ void* _AlignedAllocator_Base::alloc_impl( size_t n , size_t alignment)
|
||||
|
||||
ptr = static_cast<char*>( malloc( n + alignment + sizeof( int ) ) );
|
||||
|
||||
if( ptr == NULL ) std::bad_alloc;
|
||||
if( ptr == NULL ) throw std::bad_alloc{};
|
||||
|
||||
ptr2 = ptr + sizeof( int );
|
||||
aligned_ptr = ptr2 + ( alignment - ( ( size_t ) ptr2 & align_mask ) );
|
||||
|
||||
Reference in New Issue
Block a user