diff --git a/LICENSE.MIT.txt b/LICENSE.MIT.txt new file mode 100644 index 000000000..764a44ba7 --- /dev/null +++ b/LICENSE.MIT.txt @@ -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. diff --git a/include/Memory.h b/include/Memory.h index a739cae27..f4cc126e0 100644 --- a/include/Memory.h +++ b/include/Memory.h @@ -1,5 +1,5 @@ /* - * MemoryManager.h + * Memory.h * * Copyright (c) 2017 Lukas W * Copyright (c) 2014 Simon Symeonidis @@ -32,25 +32,35 @@ #include #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 MmCounter; + typedef NiftyCounterTL ThreadGuard; }; +static MemoryManager::MmCounter _mm_counter; + template -struct MmAllocator +class MmAllocator { +public: + MmAllocator() = default; + template< class U > MmAllocator( const MmAllocator& other ) {} typedef T value_type; - template struct rebind { typedef MmAllocator other; }; + template struct rebind { typedef MmAllocator other; }; + T* allocate( std::size_t n ) { diff --git a/include/NiftyCounter.h b/include/NiftyCounter.h new file mode 100644 index 000000000..75128e40e --- /dev/null +++ b/include/NiftyCounter.h @@ -0,0 +1,60 @@ +/* + * NiftyCounter.h + * + * Copyright (c) 2018 Lukas W + * + * 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 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 class _NiftyCounterCD_Base : public _NiftyCounter_Base +{ + friend class _NiftyCounter_Base; +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 class NiftyCounter : public _NiftyCounterCD_Base, C,D> +{ + friend class _NiftyCounterCD_Base, C,D>; +private: + static int s_count; +}; +template int NiftyCounter::s_count = 0; + +/// Thread-local version of NiftyCounter +template class NiftyCounterTL : public _NiftyCounterCD_Base, C,D> +{ + friend class _NiftyCounterCD_Base, C,D>; +private: + thread_local static int s_count; +}; +template thread_local int NiftyCounterTL::s_count = 0; diff --git a/src/core/Memory.cpp b/src/core/Memory.cpp index 1a870d68c..9f3df1f07 100644 --- a/src/core/Memory.cpp +++ b/src/core/Memory.cpp @@ -1,7 +1,7 @@ /* - * MemoryManager.cpp + * Memory.cpp * - * Copyright (c) 2017 Lukas W + * Copyright (c) 2018 Lukas W * Copyright (c) 2014 Simon Symeonidis * Copyright (c) 2004-2014 Tobias Doerffel * @@ -30,35 +30,6 @@ #include #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( 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 ) );