From 2a0890938049bbe5ddef25fc36f4f6b515bea3e9 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Thu, 30 Nov 2017 12:39:15 +0100 Subject: [PATCH 01/28] Move aligned malloc to MemoryManager.h, port to stl allocator --- include/MemoryHelper.h | 42 ------------------------ include/MemoryManager.h | 36 ++++++++++++++++++++- src/core/CMakeLists.txt | 1 - src/core/MemoryHelper.cpp | 65 -------------------------------------- src/core/MemoryManager.cpp | 29 +++++++++++++++++ src/core/Mixer.cpp | 10 +++--- 6 files changed, 69 insertions(+), 114 deletions(-) delete mode 100644 include/MemoryHelper.h delete mode 100644 src/core/MemoryHelper.cpp diff --git a/include/MemoryHelper.h b/include/MemoryHelper.h deleted file mode 100644 index 7bd31bf2b68..00000000000 --- a/include/MemoryHelper.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2014 Simon Symeonidis - * Copyright (c) 2004-2014 Tobias Doerffel - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - - -#ifndef MEMORY_HELPER_H -#define MEMORY_HELPER_H - -/** - * Helper class to alocate aligned memory and free it. - */ -class MemoryHelper { -public: - - static void* alignedMalloc( size_t ); - - static void alignedFree( void* ); - -private: -}; - -#endif - diff --git a/include/MemoryManager.h b/include/MemoryManager.h index 4c225e026a9..a739cae27a8 100644 --- a/include/MemoryManager.h +++ b/include/MemoryManager.h @@ -2,8 +2,9 @@ * MemoryManager.h * * Copyright (c) 2017 Lukas W + * Copyright (c) 2014 Simon Symeonidis * Copyright (c) 2014 Vesa Kivimäki - * Copyright (c) 2007-2014 Tobias Doerffel + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of LMMS - https://lmms.io * @@ -62,8 +63,41 @@ struct MmAllocator } typedef std::vector > vector; + +private: + MemoryManager::ThreadGuard m_threadGuard; }; +class _AlignedAllocator_Base +{ +protected: + void* alloc_impl( size_t n, size_t alignment ); + void dealloc_impl( void* p ); +}; + +template +class AlignedAllocator : _AlignedAllocator_Base +{ +public: + typedef T value_type; + template struct rebind { typedef MmAllocator other; }; + + AlignedAllocator( size_t alignment = 16 ) + : alignment(alignment) {} + + T* allocate( std::size_t n ) + { + return reinterpret_cast( alloc_impl( sizeof(T) * n, alignment ) ); + } + + void deallocate( T* p, std::size_t ) + { + dealloc_impl( p ); + } + +private: + std::size_t alignment; +}; #define MM_OPERATORS \ public: \ diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index ba41e089c7a..7a3484149ec 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -31,7 +31,6 @@ set(LMMS_SRCS core/LadspaManager.cpp core/LfoController.cpp core/LocklessAllocator.cpp - core/MemoryHelper.cpp core/MemoryManager.cpp core/MeterModel.cpp core/MicroTimer.cpp diff --git a/src/core/MemoryHelper.cpp b/src/core/MemoryHelper.cpp deleted file mode 100644 index eb5a24d4449..00000000000 --- a/src/core/MemoryHelper.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2014 Simon Symeonidis - * Copyright (c) 2008-2014 Tobias Doerffel - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#include - -#include "lmms_basics.h" -#include "MemoryHelper.h" - -/** - * Allocate a number of bytes and return them. - * @param byteNum is the number of bytes - */ -void* MemoryHelper::alignedMalloc( size_t byteNum ) -{ - char *ptr, *ptr2, *aligned_ptr; - int align_mask = ALIGN_SIZE - 1; - - ptr = static_cast( malloc( byteNum + ALIGN_SIZE + sizeof( int ) ) ); - - if( ptr == NULL ) return NULL; - - ptr2 = ptr + sizeof( int ); - aligned_ptr = ptr2 + ( ALIGN_SIZE - ( ( size_t ) ptr2 & align_mask ) ); - - ptr2 = aligned_ptr - sizeof( int ); - *( ( int* ) ptr2 ) = ( int )( aligned_ptr - ptr ); - - return aligned_ptr; -} - - -/** - * Free an aligned buffer - * @param _buffer is the buffer to free - */ -void MemoryHelper::alignedFree( void* _buffer ) -{ - if( _buffer ) - { - int *ptr2 = static_cast( _buffer ) - 1; - _buffer = static_cast( _buffer ) - *ptr2; - free( _buffer ); - } -} - diff --git a/src/core/MemoryManager.cpp b/src/core/MemoryManager.cpp index d0932e4f17b..06368172e6d 100644 --- a/src/core/MemoryManager.cpp +++ b/src/core/MemoryManager.cpp @@ -2,6 +2,8 @@ * MemoryManager.cpp * * Copyright (c) 2017 Lukas W + * Copyright (c) 2014 Simon Symeonidis + * Copyright (c) 2004-2014 Tobias Doerffel * * This file is part of LMMS - https://lmms.io * @@ -75,3 +77,30 @@ void MemoryManager::free(void * ptr) Q_ASSERT_X(rpmalloc_is_thread_initialized(), "MemoryManager::free", "Thread not initialized"); return rpfree(ptr); } + +void* _AlignedAllocator_Base::alloc_impl( size_t n , size_t alignment) +{ + char *ptr, *ptr2, *aligned_ptr; + int align_mask = alignment - 1; + + ptr = static_cast( malloc( n + alignment + sizeof( int ) ) ); + + if( ptr == NULL ) std::bad_alloc; + + ptr2 = ptr + sizeof( int ); + aligned_ptr = ptr2 + ( alignment - ( ( size_t ) ptr2 & align_mask ) ); + + ptr2 = aligned_ptr - sizeof( int ); + *( ( int* ) ptr2 ) = ( int )( aligned_ptr - ptr ); + + return aligned_ptr; +} + +void _AlignedAllocator_Base::dealloc_impl(void* p) +{ + if ( !p ) return; + + int *ptr2 = static_cast( p ) - 1; + p = static_cast( p ) - *ptr2; + free( p ); +} diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 2550b072e76..8d3a6c2cba5 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -36,7 +36,7 @@ #include "NotePlayHandle.h" #include "ConfigManager.h" #include "SamplePlayHandle.h" -#include "MemoryHelper.h" +#include "MemoryManager.h" // platform-specific audio-interface-classes #include "AudioAlsa.h" @@ -136,11 +136,10 @@ Mixer::Mixer( bool renderOnly ) : // now that framesPerPeriod is fixed initialize global BufferManager BufferManager::init( m_framesPerPeriod ); + AlignedAllocator alloc; for( int i = 0; i < 3; i++ ) { - m_readBuf = (surroundSampleFrame*) - MemoryHelper::alignedMalloc( m_framesPerPeriod * - sizeof( surroundSampleFrame ) ); + m_readBuf = alloc.allocate( m_framesPerPeriod ); BufferManager::clear( m_readBuf, m_framesPerPeriod ); m_bufferPool.push_back( m_readBuf ); @@ -189,9 +188,10 @@ Mixer::~Mixer() delete m_midiClient; delete m_audioDev; + AlignedAllocator alloc; for( int i = 0; i < 3; i++ ) { - MemoryHelper::alignedFree( m_bufferPool[i] ); + alloc.deallocate( m_bufferPool[i], m_framesPerPeriod ); } for( int i = 0; i < 2; ++i ) From 3c73270c238d6d6f5f4dfa19776df002bcd85555 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Thu, 30 Nov 2017 13:19:06 +0100 Subject: [PATCH 02/28] Rename MemoryManager.h to Memory.h --- include/AudioPort.h | 2 +- include/AutomatableModel.h | 2 +- include/BasicFilters.h | 2 +- include/DataFile.h | 2 +- include/Delay.h | 2 +- include/DetuningHelper.h | 2 +- include/Effect.h | 2 +- include/Instrument.h | 2 +- include/{MemoryManager.h => Memory.h} | 0 include/MidiEventProcessor.h | 2 +- include/NotePlayHandle.h | 2 +- include/PlayHandle.h | 2 +- include/Plugin.h | 2 +- include/RingBuffer.h | 2 +- include/SampleBuffer.h | 2 +- include/ValueBuffer.h | 2 +- plugins/FreeBoy/Gb_Apu_Buffer.h | 2 +- plugins/GigPlayer/GigPlayer.h | 2 +- plugins/LadspaEffect/LadspaEffect.cpp | 2 +- plugins/Xpressive/ExprSynth.h | 2 +- plugins/bit_invader/bit_invader.h | 2 +- plugins/kicker/CMakeLists.txt | 2 +- plugins/kicker/KickerOsc.h | 2 +- plugins/nes/Nes.h | 2 +- plugins/patman/patman.h | 2 +- plugins/sf2_player/sf2_player.h | 2 +- plugins/sfxr/sfxr.h | 2 +- plugins/vibed/string_container.h | 2 +- plugins/watsyn/Watsyn.h | 2 +- src/core/BufferManager.cpp | 2 +- src/core/CMakeLists.txt | 2 +- src/core/{MemoryManager.cpp => Memory.cpp} | 3 ++- src/core/Mixer.cpp | 2 +- 33 files changed, 33 insertions(+), 32 deletions(-) rename include/{MemoryManager.h => Memory.h} (100%) rename src/core/{MemoryManager.cpp => Memory.cpp} (99%) diff --git a/include/AudioPort.h b/include/AudioPort.h index 2842c6a1768..a5c29b32e45 100644 --- a/include/AudioPort.h +++ b/include/AudioPort.h @@ -30,7 +30,7 @@ #include #include -#include "MemoryManager.h" +#include "Memory.h" #include "PlayHandle.h" class EffectChain; diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 3e0b6143da3..0f2216c486e 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -32,7 +32,7 @@ #include "Model.h" #include "MidiTime.h" #include "ValueBuffer.h" -#include "MemoryManager.h" +#include "Memory.h" #include "ModelVisitor.h" // simple way to map a property of a view to a model diff --git a/include/BasicFilters.h b/include/BasicFilters.h index c3a76d36e0d..9a8e8191567 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -41,7 +41,7 @@ #include "lmms_basics.h" #include "lmms_constants.h" #include "interpolation.h" -#include "MemoryManager.h" +#include "Memory.h" template class BasicFilters; diff --git a/include/DataFile.h b/include/DataFile.h index 5890693da0a..59e50b028b2 100644 --- a/include/DataFile.h +++ b/include/DataFile.h @@ -30,7 +30,7 @@ #include #include "lmms_export.h" -#include "MemoryManager.h" +#include "Memory.h" class QTextStream; diff --git a/include/Delay.h b/include/Delay.h index 0e32a7635b3..7a709fd2c2c 100644 --- a/include/Delay.h +++ b/include/Delay.h @@ -30,7 +30,7 @@ #include "lmms_basics.h" #include "lmms_math.h" #include "interpolation.h" -#include "MemoryManager.h" +#include "Memory.h" // brief usage diff --git a/include/DetuningHelper.h b/include/DetuningHelper.h index de0acc82603..0cccf994363 100644 --- a/include/DetuningHelper.h +++ b/include/DetuningHelper.h @@ -27,7 +27,7 @@ #define DETUNING_HELPER_H #include "InlineAutomation.h" -#include "MemoryManager.h" +#include "Memory.h" class DetuningHelper : public InlineAutomation { diff --git a/include/Effect.h b/include/Effect.h index 4dc50e8a478..eaa5f650655 100644 --- a/include/Effect.h +++ b/include/Effect.h @@ -31,7 +31,7 @@ #include "Mixer.h" #include "AutomatableModel.h" #include "TempoSyncKnobModel.h" -#include "MemoryManager.h" +#include "Memory.h" class EffectChain; class EffectControls; diff --git a/include/Instrument.h b/include/Instrument.h index 2179a1f721f..241bff9f759 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -29,7 +29,7 @@ #include #include "lmms_export.h" #include "lmms_basics.h" -#include "MemoryManager.h" +#include "Memory.h" #include "MidiTime.h" #include "Plugin.h" diff --git a/include/MemoryManager.h b/include/Memory.h similarity index 100% rename from include/MemoryManager.h rename to include/Memory.h diff --git a/include/MidiEventProcessor.h b/include/MidiEventProcessor.h index b48f75d2bfb..7022eaf3a81 100644 --- a/include/MidiEventProcessor.h +++ b/include/MidiEventProcessor.h @@ -27,7 +27,7 @@ #include "MidiEvent.h" #include "MidiTime.h" -#include "MemoryManager.h" +#include "Memory.h" // all classes being able to process MIDI-events should inherit from this class MidiEventProcessor diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index ae55c9ebb6a..99add818564 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -32,7 +32,7 @@ #include "Note.h" #include "PlayHandle.h" #include "Track.h" -#include "MemoryManager.h" +#include "Memory.h" class QReadWriteLock; class InstrumentTrack; diff --git a/include/PlayHandle.h b/include/PlayHandle.h index 1760e1ec7c1..6e71c7619b4 100644 --- a/include/PlayHandle.h +++ b/include/PlayHandle.h @@ -30,7 +30,7 @@ #include "lmms_export.h" -#include "MemoryManager.h" +#include "Memory.h" #include "ThreadableJob.h" #include "lmms_basics.h" diff --git a/include/Plugin.h b/include/Plugin.h index af42b0f1028..2c5f90669cf 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -31,7 +31,7 @@ #include "JournallingObject.h" #include "Model.h" -#include "MemoryManager.h" +#include "Memory.h" class QWidget; diff --git a/include/RingBuffer.h b/include/RingBuffer.h index c761616bd78..99c88851187 100644 --- a/include/RingBuffer.h +++ b/include/RingBuffer.h @@ -30,7 +30,7 @@ #include #include "lmms_basics.h" #include "lmms_math.h" -#include "MemoryManager.h" +#include "Memory.h" class LMMS_EXPORT RingBuffer : public QObject { diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h index 26e85602508..4eae226fd77 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -36,7 +36,7 @@ #include "lmms_basics.h" #include "lmms_math.h" #include "shared_object.h" -#include "MemoryManager.h" +#include "Memory.h" class QPainter; diff --git a/include/ValueBuffer.h b/include/ValueBuffer.h index f9869de8888..5f847f63260 100644 --- a/include/ValueBuffer.h +++ b/include/ValueBuffer.h @@ -28,7 +28,7 @@ #include -#include "MemoryManager.h" +#include "Memory.h" #include "lmms_export.h" class LMMS_EXPORT ValueBuffer : public std::vector diff --git a/plugins/FreeBoy/Gb_Apu_Buffer.h b/plugins/FreeBoy/Gb_Apu_Buffer.h index 5228b7b8afd..01e44fbcd78 100644 --- a/plugins/FreeBoy/Gb_Apu_Buffer.h +++ b/plugins/FreeBoy/Gb_Apu_Buffer.h @@ -25,7 +25,7 @@ #include "Gb_Apu.h" #include "Multi_Buffer.h" -#include "MemoryManager.h" +#include "Memory.h" class Gb_Apu_Buffer : public Gb_Apu { MM_OPERATORS diff --git a/plugins/GigPlayer/GigPlayer.h b/plugins/GigPlayer/GigPlayer.h index b9467b91bbf..49465be2ae9 100644 --- a/plugins/GigPlayer/GigPlayer.h +++ b/plugins/GigPlayer/GigPlayer.h @@ -38,7 +38,7 @@ #include "Knob.h" #include "LcdSpinBox.h" #include "LedCheckbox.h" -#include "MemoryManager.h" +#include "Memory.h" #include "gig.h" class GigInstrumentView; diff --git a/plugins/LadspaEffect/LadspaEffect.cpp b/plugins/LadspaEffect/LadspaEffect.cpp index d7e66bf47aa..7199825214f 100644 --- a/plugins/LadspaEffect/LadspaEffect.cpp +++ b/plugins/LadspaEffect/LadspaEffect.cpp @@ -38,7 +38,7 @@ #include "EffectChain.h" #include "AutomationPattern.h" #include "ControllerConnection.h" -#include "MemoryManager.h" +#include "Memory.h" #include "ValueBuffer.h" #include "Song.h" diff --git a/plugins/Xpressive/ExprSynth.h b/plugins/Xpressive/ExprSynth.h index bb25fd036dd..01e98ebe923 100644 --- a/plugins/Xpressive/ExprSynth.h +++ b/plugins/Xpressive/ExprSynth.h @@ -31,7 +31,7 @@ #include "AutomatableModel.h" #include "Graph.h" #include "Instrument.h" -#include "MemoryManager.h" +#include "Memory.h" class ExprFrontData; diff --git a/plugins/bit_invader/bit_invader.h b/plugins/bit_invader/bit_invader.h index 793831e4aab..07562c76ecb 100644 --- a/plugins/bit_invader/bit_invader.h +++ b/plugins/bit_invader/bit_invader.h @@ -33,7 +33,7 @@ #include "Knob.h" #include "PixmapButton.h" #include "LedCheckbox.h" -#include "MemoryManager.h" +#include "Memory.h" class oscillator; class bitInvaderView; diff --git a/plugins/kicker/CMakeLists.txt b/plugins/kicker/CMakeLists.txt index 0ac9f87b50b..1334d11aa33 100644 --- a/plugins/kicker/CMakeLists.txt +++ b/plugins/kicker/CMakeLists.txt @@ -1,3 +1,3 @@ INCLUDE(BuildPlugin) -BUILD_PLUGIN(kicker kicker.cpp kicker.h MOCFILES kicker.h EMBEDDED_RESOURCES artwork.png logo.png) +BUILD_PLUGIN(kicker kicker.cpp kicker.h KickerOsc.h MOCFILES kicker.h EMBEDDED_RESOURCES artwork.png logo.png) diff --git a/plugins/kicker/KickerOsc.h b/plugins/kicker/KickerOsc.h index 1375725b32e..4fd66a6bb33 100644 --- a/plugins/kicker/KickerOsc.h +++ b/plugins/kicker/KickerOsc.h @@ -31,7 +31,7 @@ #include "lmms_math.h" #include "interpolation.h" -#include "MemoryManager.h" +#include "Memory.h" template diff --git a/plugins/nes/Nes.h b/plugins/nes/Nes.h index bbf326d3271..9e093b5334b 100644 --- a/plugins/nes/Nes.h +++ b/plugins/nes/Nes.h @@ -34,7 +34,7 @@ #include "TempoSyncKnob.h" #include "NotePlayHandle.h" #include "PixmapButton.h" -#include "MemoryManager.h" +#include "Memory.h" #define makeknob( name, x, y, hint, unit, oname ) \ diff --git a/plugins/patman/patman.h b/plugins/patman/patman.h index 8d5689b7363..5b7f6fd6546 100644 --- a/plugins/patman/patman.h +++ b/plugins/patman/patman.h @@ -30,7 +30,7 @@ #include "InstrumentView.h" #include "SampleBuffer.h" #include "AutomatableModel.h" -#include "MemoryManager.h" +#include "Memory.h" class PixmapButton; diff --git a/plugins/sf2_player/sf2_player.h b/plugins/sf2_player/sf2_player.h index 1dde587ad5e..8127d62329e 100644 --- a/plugins/sf2_player/sf2_player.h +++ b/plugins/sf2_player/sf2_player.h @@ -37,7 +37,7 @@ #include "LcdSpinBox.h" #include "LedCheckbox.h" #include "fluidsynthshims.h" -#include "MemoryManager.h" +#include "Memory.h" class sf2InstrumentView; class sf2Font; diff --git a/plugins/sfxr/sfxr.h b/plugins/sfxr/sfxr.h index 20ae54c96fe..1214aeb37a1 100644 --- a/plugins/sfxr/sfxr.h +++ b/plugins/sfxr/sfxr.h @@ -34,7 +34,7 @@ #include "Graph.h" #include "PixmapButton.h" #include "LedCheckbox.h" -#include "MemoryManager.h" +#include "Memory.h" enum SfxrWaves diff --git a/plugins/vibed/string_container.h b/plugins/vibed/string_container.h index f615080790e..08ab7879854 100644 --- a/plugins/vibed/string_container.h +++ b/plugins/vibed/string_container.h @@ -27,7 +27,7 @@ #include #include "vibrating_string.h" -#include "MemoryManager.h" +#include "Memory.h" class stringContainer diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index 079e532e41a..1dd6f6b87e8 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -35,7 +35,7 @@ #include "NotePlayHandle.h" #include "PixmapButton.h" #include -#include "MemoryManager.h" +#include "Memory.h" #define makeknob( name, x, y, hint, unit, oname ) \ diff --git a/src/core/BufferManager.cpp b/src/core/BufferManager.cpp index 2df7bcaa989..ed658866ca0 100644 --- a/src/core/BufferManager.cpp +++ b/src/core/BufferManager.cpp @@ -28,7 +28,7 @@ #include "Engine.h" #include "Mixer.h" -#include "MemoryManager.h" +#include "Memory.h" static fpp_t framesPerPeriod; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 7a3484149ec..c84c222bd80 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -31,7 +31,7 @@ set(LMMS_SRCS core/LadspaManager.cpp core/LfoController.cpp core/LocklessAllocator.cpp - core/MemoryManager.cpp + core/Memory.cpp core/MeterModel.cpp core/MicroTimer.cpp core/Mixer.cpp diff --git a/src/core/MemoryManager.cpp b/src/core/Memory.cpp similarity index 99% rename from src/core/MemoryManager.cpp rename to src/core/Memory.cpp index 06368172e6d..1a870d68c1b 100644 --- a/src/core/MemoryManager.cpp +++ b/src/core/Memory.cpp @@ -25,7 +25,7 @@ */ -#include "MemoryManager.h" +#include "Memory.h" #include #include "rpmalloc.h" @@ -104,3 +104,4 @@ void _AlignedAllocator_Base::dealloc_impl(void* p) p = static_cast( p ) - *ptr2; free( p ); } + diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 8d3a6c2cba5..29301fa6380 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -36,7 +36,7 @@ #include "NotePlayHandle.h" #include "ConfigManager.h" #include "SamplePlayHandle.h" -#include "MemoryManager.h" +#include "Memory.h" // platform-specific audio-interface-classes #include "AudioAlsa.h" From 1340c273c7abd69f28cf78a7702c3ad4da1af953 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sun, 15 Apr 2018 21:45:30 +0200 Subject: [PATCH 03/28] 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 --- LICENSE.MIT.txt | 18 +++++++++++++ include/Memory.h | 28 +++++++++++++------- include/NiftyCounter.h | 60 ++++++++++++++++++++++++++++++++++++++++++ src/core/Memory.cpp | 55 ++++++++++++++++---------------------- 4 files changed, 120 insertions(+), 41 deletions(-) create mode 100644 LICENSE.MIT.txt create mode 100644 include/NiftyCounter.h diff --git a/LICENSE.MIT.txt b/LICENSE.MIT.txt new file mode 100644 index 00000000000..764a44ba728 --- /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 a739cae27a8..f4cc126e078 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 00000000000..75128e40ee4 --- /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 1a870d68c1b..9f3df1f079a 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 ) ); From 1cd8e1594230d4cd0a9a7dbd717f95f099272379 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sun, 15 Apr 2018 22:21:25 +0200 Subject: [PATCH 04/28] Replace LocklessAllocator with new MemoryPool class MemoryPool maintains a free list of pre-allocated entries stored in a libcds MPMC Queue. In contrast to LocklessAllocator, it's a lot faster, less (and less complex) code to maintain for us and it doesn't fail when it's full. --- .gitmodules | 3 + cmake/modules/CheckSubmodules.cmake | 4 +- include/LocklessAllocator.h | 82 -------------- include/LocklessList.h | 11 +- include/MemoryPool.h | 82 ++++++++++++++ include/libcds.h | 15 +++ src/3rdparty/CMakeLists.txt | 2 + src/3rdparty/libcds | 1 + src/CMakeLists.txt | 1 + src/core/CMakeLists.txt | 4 +- src/core/LocklessAllocator.cpp | 164 ---------------------------- src/core/MemoryPool.cpp | 121 ++++++++++++++++++++ src/core/libcds.cpp | 36 ++++++ tests/CMakeLists.txt | 1 + tests/src/core/MemoryPoolTest.cpp | 58 ++++++++++ 15 files changed, 330 insertions(+), 255 deletions(-) delete mode 100644 include/LocklessAllocator.h create mode 100644 include/MemoryPool.h create mode 100644 include/libcds.h create mode 160000 src/3rdparty/libcds delete mode 100644 src/core/LocklessAllocator.cpp create mode 100644 src/core/MemoryPool.cpp create mode 100644 src/core/libcds.cpp create mode 100644 tests/src/core/MemoryPoolTest.cpp diff --git a/.gitmodules b/.gitmodules index 28d6c5d46de..cf867624303 100644 --- a/.gitmodules +++ b/.gitmodules @@ -31,6 +31,9 @@ [submodule "src/3rdparty/mingw-std-threads"] path = src/3rdparty/mingw-std-threads url = https://github.com/meganz/mingw-std-threads.git +[submodule "src/3rdparty/libcds"] + path = src/3rdparty/libcds + url = https://github.com/khizmax/libcds.git [submodule "doc/wiki"] path = doc/wiki url = https://github.com/lmms/lmms.wiki.git diff --git a/cmake/modules/CheckSubmodules.cmake b/cmake/modules/CheckSubmodules.cmake index 65e5be08bf9..23b52f140b4 100644 --- a/cmake/modules/CheckSubmodules.cmake +++ b/cmake/modules/CheckSubmodules.cmake @@ -42,8 +42,8 @@ SET(ENV{LC_ALL} "C") SET(ENV{LANG} "en_US") # Assume alpha-numeric paths -STRING(REGEX MATCHALL "path = [-0-9A-Za-z/]+" SUBMODULE_LIST ${SUBMODULE_DATA}) -STRING(REGEX MATCHALL "url = [.:%-0-9A-Za-z/]+" SUBMODULE_URL_LIST ${SUBMODULE_DATA}) +STRING(REGEX MATCHALL "path = [-0-9A-Za-z/_]+" SUBMODULE_LIST ${SUBMODULE_DATA}) +STRING(REGEX MATCHALL "url = [.:%-0-9A-Za-z/_]+" SUBMODULE_URL_LIST ${SUBMODULE_DATA}) FOREACH(_part ${SUBMODULE_LIST}) STRING(REPLACE "path = " "" SUBMODULE_PATH ${_part}) diff --git a/include/LocklessAllocator.h b/include/LocklessAllocator.h deleted file mode 100644 index e7e265680b8..00000000000 --- a/include/LocklessAllocator.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * LocklessAllocator.h - allocator with lockless alloc and free - * - * Copyright (c) 2016 Javier Serrano Polo - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#ifndef LOCKLESS_ALLOCATOR_H -#define LOCKLESS_ALLOCATOR_H - -#include -#include - -class LocklessAllocator -{ -public: - LocklessAllocator( size_t nmemb, size_t size ); - virtual ~LocklessAllocator(); - void * alloc(); - void free( void * ptr ); - - -private: - char * m_pool; - size_t m_capacity; - size_t m_elementSize; - - std::atomic_int * m_freeState; - size_t m_freeStateSets; - - std::atomic_int m_available; - std::atomic_int m_startIndex; - -} ; - - - - -template -class LocklessAllocatorT : private LocklessAllocator -{ -public: - LocklessAllocatorT( size_t nmemb ) : - LocklessAllocator( nmemb, sizeof( T ) ) - { - } - - virtual ~LocklessAllocatorT() - { - } - - T * alloc() - { - return (T *)LocklessAllocator::alloc(); - } - - void free( T * ptr ) - { - LocklessAllocator::free( ptr ); - } - -} ; - - -#endif diff --git a/include/LocklessList.h b/include/LocklessList.h index 05df56f41af..1d32ddc23fc 100644 --- a/include/LocklessList.h +++ b/include/LocklessList.h @@ -25,7 +25,7 @@ #ifndef LOCKLESS_LIST_H #define LOCKLESS_LIST_H -#include "LocklessAllocator.h" +#include "MemoryPool.h" #include @@ -41,7 +41,7 @@ class LocklessList LocklessList( size_t size ) : m_first(nullptr), - m_allocator(new LocklessAllocatorT(size)) + m_allocator(new MemoryPool(size)) { } @@ -52,7 +52,7 @@ class LocklessList void push( T value ) { - Element * e = m_allocator->alloc(); + Element * e = m_allocator->allocate(); e->value = value; e->next = m_first.load(std::memory_order_relaxed); @@ -81,14 +81,13 @@ class LocklessList void free( Element * e ) { - m_allocator->free( e ); + m_allocator->destroy( e ); } private: std::atomic m_first; - LocklessAllocatorT * m_allocator; - + MemoryPool * m_allocator; } ; diff --git a/include/MemoryPool.h b/include/MemoryPool.h new file mode 100644 index 00000000000..1166a5a6fa9 --- /dev/null +++ b/include/MemoryPool.h @@ -0,0 +1,82 @@ +/* + * MemoryPool.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 + +#include +#include + +class _MemoryPool_Private; + +class _MemoryPool_Base +{ +public: + _MemoryPool_Base(size_t size, size_t nmemb); + virtual ~_MemoryPool_Base(); + void * allocate(); + void * allocate_bounded(); + void deallocate(void * ptr); + +private: + const std::unique_ptr<_MemoryPool_Private> _imp; +}; + +/// Thread-safe, lockless memory pool. Only supports allocate(n) with n=1. When +/// the pool is exhausted, MmAllocator is used. +template +class MemoryPool : private _MemoryPool_Base +{ +public: + using value_type = T; + template struct rebind { typedef MemoryPool other; }; + + MemoryPool(size_t nmemb) : _MemoryPool_Base(sizeof(T), nmemb) {} + + T * allocate(size_t n = 1) + { + if (n != 1) { throw std::bad_alloc{}; } + return reinterpret_cast(_MemoryPool_Base::allocate()); + } + + T * allocate_bounded() + { + return reinterpret_cast(_MemoryPool_Base::allocate_bounded()); + } + + void deallocate(T * ptr, size_t n = 1) + { + _MemoryPool_Base::deallocate(ptr); + } + + template + T * construct(Args&&... args) + { + T* buffer = allocate(); + return ::new ((void*)buffer) T(std::forward(args)...); + } + + template + T * construct_bounded(Args&&... args) + { + T* buffer = allocate_bounded(); + if (buffer) { + ::new ((void*)buffer) T(std::forward(args)...); + } + return buffer; + } + + void destroy(T* ptr) + { + ptr->~T(); + deallocate(ptr); + } +} ; diff --git a/include/libcds.h b/include/libcds.h new file mode 100644 index 00000000000..0d095d03cce --- /dev/null +++ b/include/libcds.h @@ -0,0 +1,15 @@ +#pragma once + +#include "NiftyCounter.h" + +namespace _cdslib +{ + void init(); + void deinit(); + void thread_init(); + void thread_deinit(); + + static NiftyCounter _counter; + static NiftyCounterTL _thread_counter; +} + diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index 473e7702f09..b2d73accc5c 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -10,3 +10,5 @@ ENDIF() ADD_SUBDIRECTORY(rpmalloc) ADD_SUBDIRECTORY(weakjack) + +ADD_SUBDIRECTORY(libcds) diff --git a/src/3rdparty/libcds b/src/3rdparty/libcds new file mode 160000 index 00000000000..e5bba766b93 --- /dev/null +++ b/src/3rdparty/libcds @@ -0,0 +1 @@ +Subproject commit e5bba766b939f96b5f47fe470a3711ff3afe9ee2 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ac6bf1332f..1cfe0e2087f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -168,6 +168,7 @@ SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} ${SNDFILE_LIBRARIES} ${EXTRA_LIBRARIES} rpmalloc + cds-s ) # Expose required libs for tests binary diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index c84c222bd80..4e8d7ef8a51 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -30,8 +30,8 @@ set(LMMS_SRCS core/LadspaControl.cpp core/LadspaManager.cpp core/LfoController.cpp - core/LocklessAllocator.cpp core/Memory.cpp + core/MemoryPool.cpp core/MeterModel.cpp core/MicroTimer.cpp core/Mixer.cpp @@ -99,5 +99,7 @@ set(LMMS_SRCS core/midi/MidiTime.cpp core/midi/MidiWinMM.cpp + core/libcds.cpp + PARENT_SCOPE ) diff --git a/src/core/LocklessAllocator.cpp b/src/core/LocklessAllocator.cpp deleted file mode 100644 index 4839a7bd956..00000000000 --- a/src/core/LocklessAllocator.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* - * LocklessAllocator.cpp - allocator with lockless alloc and free - * - * Copyright (c) 2016 Javier Serrano Polo - * - * This file is part of LMMS - https://lmms.io - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program (see COPYING); if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - */ - -#include "LocklessAllocator.h" - -#include -#include - -#include "lmmsconfig.h" - -#ifndef LMMS_BUILD_WIN32 -#include -#endif - -static const size_t SIZEOF_SET = sizeof( int ) * 8; - - -static size_t align( size_t size, size_t alignment ) -{ - size_t misalignment = size % alignment; - if( misalignment ) - { - size += alignment - misalignment; - } - return size; -} - - - - -LocklessAllocator::LocklessAllocator( size_t nmemb, size_t size ) -{ - m_capacity = align( nmemb, SIZEOF_SET ); - m_elementSize = align( size, sizeof( void * ) ); - m_pool = new char[m_capacity * m_elementSize]; - - m_freeStateSets = m_capacity / SIZEOF_SET; - m_freeState = new std::atomic_int[m_freeStateSets]; - std::fill(m_freeState, m_freeState + m_freeStateSets, 0); - - m_available = m_capacity; - m_startIndex = 0; -} - - - - -LocklessAllocator::~LocklessAllocator() -{ - int available = m_available; - if( available != m_capacity ) - { - fprintf( stderr, "LocklessAllocator: " - "Destroying with elements still allocated\n" ); - } - - delete[] m_pool; - delete[] m_freeState; -} - - - - -#ifdef LMMS_BUILD_WIN32 -static int ffs( int i ) -{ - if( !i ) - { - return 0; - } - for( int j = 0;; ) - { - if( i & 1 << j++ ) - { - return j; - } - } -} -#endif - - - - -void * LocklessAllocator::alloc() -{ - // Some of these CAS loops could probably use relaxed atomics, as discussed - // in http://en.cppreference.com/w/cpp/atomic/atomic/compare_exchange. - // Let's use sequentially-consistent ops to be safe for now. - int available = m_available.load(); - do - { - if( !available ) - { - fprintf( stderr, "LocklessAllocator: No free space\n" ); - return NULL; - } - } - while (!m_available.compare_exchange_weak(available, available - 1)); - - const size_t startIndex = m_startIndex++ % m_freeStateSets; - for (size_t set = startIndex;; set = ( set + 1 ) % m_freeStateSets) - { - for (int freeState = m_freeState[set]; freeState != -1;) - { - int bit = ffs( ~freeState ) - 1; - if (m_freeState[set].compare_exchange_weak(freeState, - freeState | 1 << bit ) ) - { - return m_pool + ( SIZEOF_SET * set + bit ) - * m_elementSize; - } - } - } -} - - - - -void LocklessAllocator::free( void * ptr ) -{ - ptrdiff_t diff = (char *)ptr - m_pool; - if( diff < 0 || diff % m_elementSize ) - { -invalid: - fprintf( stderr, "LocklessAllocator: Invalid pointer\n" ); - return; - } - size_t offset = diff / m_elementSize; - if( offset >= m_capacity ) - { - goto invalid; - } - size_t set = offset / SIZEOF_SET; - int bit = offset % SIZEOF_SET; - int mask = 1 << bit; - int prevState = m_freeState[set].fetch_and(~mask); - if ( !( prevState & mask ) ) - { - fprintf( stderr, "LocklessAllocator: Block not in use\n" ); - return; - } - ++m_available; -} diff --git a/src/core/MemoryPool.cpp b/src/core/MemoryPool.cpp new file mode 100644 index 00000000000..a9cde2701d9 --- /dev/null +++ b/src/core/MemoryPool.cpp @@ -0,0 +1,121 @@ +/* + * MemoryPool.cpp + * + * 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. + * + */ + +#include "MemoryPool.h" + +#include + +#include +#include "libcds.h" + +#include "Memory.h" + +class _MemoryPool_Private : MmAllocator +{ + using Alloc = MmAllocator; +public: + _MemoryPool_Private(size_t size, size_t nmemb) + : m_freelist(nmemb) + , m_elementSize(size) + , m_numElms(nmemb) + { + m_buffer = new char[m_elementSize * m_numElms]; + for (size_t i = 0; i < m_numElms; i++) { + m_freelist.push(m_buffer + (i * m_elementSize)); + } + } + + ~_MemoryPool_Private() + { + char* ptr = nullptr; + while (m_freelist.pop(ptr)) { + if (! is_from_pool(ptr)) { + Alloc::deallocate(ptr, m_elementSize); + } + } + delete[] m_buffer; + } + + void * allocate() + { + void* ptr = allocate_bounded(); + if (ptr) { + return ptr; + } else { + qWarning() << "MemoryPool exhausted"; + return Alloc::allocate(m_elementSize); + } + } + + void * allocate_bounded() + { + char* ptr = nullptr; + m_freelist.pop(ptr); + return ptr; + } + + void deallocate(void * ptr) + { + if (is_from_pool(ptr)) { + bool pushed = m_freelist.push(reinterpret_cast(ptr)); + assert(pushed); + } else { + do_deallocate(ptr); + } + } + +private: + void* do_allocate() + { + return Alloc::allocate(m_elementSize); + } + void do_deallocate(void* ptr) + { + Alloc::deallocate(reinterpret_cast(ptr), m_elementSize); + } + + bool is_from_pool(void* ptr) + { + auto buff = reinterpret_cast(m_buffer); + auto p = reinterpret_cast(ptr); + return p >= buff && p < (buff + (m_elementSize * m_numElms)); + } + + const size_t m_elementSize; + const size_t m_numElms; + + char* m_buffer; + cds::container::VyukovMPMCCycleQueue m_freelist; +}; + +_MemoryPool_Base::_MemoryPool_Base( size_t size, size_t nmemb ) + : _imp(new _MemoryPool_Private(size, nmemb)) +{} + +_MemoryPool_Base::~_MemoryPool_Base() +{} + +void * _MemoryPool_Base::allocate() +{ + return _imp->allocate(); +} + +void *_MemoryPool_Base::allocate_bounded() +{ + return _imp->allocate_bounded(); +} + +void _MemoryPool_Base::deallocate(void * ptr) +{ + return _imp->deallocate(ptr); +} + diff --git a/src/core/libcds.cpp b/src/core/libcds.cpp new file mode 100644 index 00000000000..ef7ac3a88bb --- /dev/null +++ b/src/core/libcds.cpp @@ -0,0 +1,36 @@ +#include "libcds.h" + +#include +#include + +#include +#include "stdshims.h" + +namespace _cdslib +{ + +static std::unique_ptr hpGC; + +void init() +{ + cds::Initialize(); + hpGC = make_unique(); +} + +void deinit() +{ + hpGC.reset(); + cds::Terminate(); +} + +void thread_init() +{ + cds::threading::Manager::attachThread(); +} + +void thread_deinit() +{ + cds::threading::Manager::detachThread(); +} + +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ddebe116c6e..c7e3a6b53ff 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -17,6 +17,7 @@ ADD_EXECUTABLE(tests src/core/AutomatableModelTest.cpp src/core/ProjectVersionTest.cpp src/core/RelativePathsTest.cpp + src/core/MemoryPoolTest.cpp src/tracks/AutomationTrackTest.cpp ) diff --git a/tests/src/core/MemoryPoolTest.cpp b/tests/src/core/MemoryPoolTest.cpp new file mode 100644 index 00000000000..2358cc40f21 --- /dev/null +++ b/tests/src/core/MemoryPoolTest.cpp @@ -0,0 +1,58 @@ +/* + * MemoryPoolTest.cpp + * + * Copyright (c) 2018 Lukas W + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "QTestSuite.h" + +#include "MemoryPool.h" + +#include +#include + +class MemoryPoolTest : QTestSuite +{ + Q_OBJECT +private slots: + void MemoryPoolTests() + { + using T = std::array; + MemoryPool pool(256); + + std::stack ptrs; + + for (int i=0; i < 256; i++) { + ptrs.push(pool.allocate_bounded()); + QVERIFY(ptrs.top()); + } + QCOMPARE(pool.allocate_bounded(), nullptr); + ptrs.push(pool.allocate()); + QVERIFY(ptrs.top()); + + while (!ptrs.empty()) { + pool.deallocate(ptrs.top()); + ptrs.pop(); + } + } +} MemoryPoolTests; + +#include "MemoryPoolTest.moc" From 3e1a96693d4863b4660dda8f3765744b649d0ff2 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 17 Apr 2018 16:52:32 +0200 Subject: [PATCH 05/28] Replace NotePlayHandleManager implementation with MemoryPool --- include/NotePlayHandle.h | 30 +----------- src/core/InstrumentFunctions.cpp | 5 +- src/core/Mixer.cpp | 10 ++-- src/core/NotePlayHandle.cpp | 69 +--------------------------- src/core/PresetPreviewPlayHandle.cpp | 2 +- src/core/main.cpp | 3 -- src/tracks/InstrumentTrack.cpp | 6 +-- 7 files changed, 15 insertions(+), 110 deletions(-) diff --git a/include/NotePlayHandle.h b/include/NotePlayHandle.h index 99add818564..717dc6b8a3c 100644 --- a/include/NotePlayHandle.h +++ b/include/NotePlayHandle.h @@ -32,7 +32,7 @@ #include "Note.h" #include "PlayHandle.h" #include "Track.h" -#include "Memory.h" +#include "MemoryPool.h" class QReadWriteLock; class InstrumentTrack; @@ -44,7 +44,6 @@ typedef QList ConstNotePlayHandleList; class LMMS_EXPORT NotePlayHandle : public PlayHandle, public Note { - MM_OPERATORS public: void * m_pluginData; std::unique_ptr> m_filter; @@ -328,31 +327,6 @@ class LMMS_EXPORT NotePlayHandle : public PlayHandle, public Note bool m_frequencyNeedsUpdate; // used to update pitch } ; - -const int INITIAL_NPH_CACHE = 256; -const int NPH_CACHE_INCREMENT = 16; - -class NotePlayHandleManager -{ - MM_OPERATORS -public: - static void init(); - static NotePlayHandle * acquire( InstrumentTrack* instrumentTrack, - const f_cnt_t offset, - const f_cnt_t frames, - const Note& noteToPlay, - NotePlayHandle* parent = NULL, - int midiEventChannel = -1, - NotePlayHandle::Origin origin = NotePlayHandle::OriginPattern ); - static void release( NotePlayHandle * nph ); - static void extend( int i ); - -private: - static NotePlayHandle ** s_available; - static QReadWriteLock s_mutex; - static std::atomic_int s_availableIndex; - static int s_size; -}; - +extern MemoryPool NotePlayHandlePool; #endif diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index 70e2c5e806e..a710262b055 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -32,7 +32,6 @@ #include "PresetPreviewPlayHandle.h" #include "stdshims.h" - InstrumentFunctionNoteStacking::ChordTable::Init InstrumentFunctionNoteStacking::ChordTable::s_initTable[] = { { QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "octave" ), { 0, -1 } }, @@ -263,7 +262,7 @@ void InstrumentFunctionNoteStacking::processNote( NotePlayHandle * _n ) // create sub-note-play-handle, only note is // different Engine::mixer()->addPlayHandle( - NotePlayHandleManager::acquire( _n->instrumentTrack(), _n->offset(), _n->frames(), note_copy, + NotePlayHandlePool.construct( _n->instrumentTrack(), _n->offset(), _n->frames(), note_copy, _n, -1, NotePlayHandle::OriginNoteStacking ) ); } @@ -502,7 +501,7 @@ void InstrumentFunctionArpeggio::processNote( NotePlayHandle * _n ) // create sub-note-play-handle, only ptr to note is different // and is_arp_note=true Engine::mixer()->addPlayHandle( - NotePlayHandleManager::acquire( _n->instrumentTrack(), + NotePlayHandlePool.construct( _n->instrumentTrack(), frames_processed, gated_frames, Note( MidiTime( 0 ), MidiTime( 0 ), sub_note_key, _n->getVolume(), diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 29301fa6380..8ad36c73bb7 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -400,7 +400,7 @@ const surroundSampleFrame * Mixer::renderNextBuffer() ( *it )->audioPort()->removePlayHandle( ( *it ) ); if( ( *it )->type() == PlayHandle::TypeNotePlayHandle ) { - NotePlayHandleManager::release( (NotePlayHandle*) *it ); + NotePlayHandlePool.destroy( (NotePlayHandle*) *it ); } else delete *it; m_playHandles.erase( it ); @@ -454,7 +454,7 @@ const surroundSampleFrame * Mixer::renderNextBuffer() ( *it )->audioPort()->removePlayHandle( ( *it ) ); if( ( *it )->type() == PlayHandle::TypeNotePlayHandle ) { - NotePlayHandleManager::release( (NotePlayHandle*) *it ); + NotePlayHandlePool.destroy( (NotePlayHandle*) *it ); } else delete *it; it = m_playHandles.erase( it ); @@ -689,7 +689,7 @@ bool Mixer::addPlayHandle( PlayHandle* handle ) if( handle->type() == PlayHandle::TypeNotePlayHandle ) { - NotePlayHandleManager::release( (NotePlayHandle*)handle ); + NotePlayHandlePool.destroy( (NotePlayHandle*)handle ); } else delete handle; @@ -742,7 +742,7 @@ void Mixer::removePlayHandle( PlayHandle * _ph ) { if( _ph->type() == PlayHandle::TypeNotePlayHandle ) { - NotePlayHandleManager::release( (NotePlayHandle*) _ph ); + NotePlayHandlePool.destroy( (NotePlayHandle*) _ph ); } else delete _ph; } @@ -768,7 +768,7 @@ void Mixer::removePlayHandlesOfTypes( Track * _track, const quint8 types ) ( *it )->audioPort()->removePlayHandle( ( *it ) ); if( ( *it )->type() == PlayHandle::TypeNotePlayHandle ) { - NotePlayHandleManager::release( (NotePlayHandle*) *it ); + NotePlayHandlePool.destroy( (NotePlayHandle*) *it ); } else delete *it; it = m_playHandles.erase( it ); diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 0039f935a5d..c7102003484 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -32,7 +32,6 @@ #include "Mixer.h" #include "Song.h" - NotePlayHandle::BaseDetuning::BaseDetuning( DetuningHelper *detuning ) : m_value( detuning ? detuning->automationPattern()->valueAt( 0 ) : 0 ) { @@ -543,69 +542,5 @@ void NotePlayHandle::resize( const bpm_t _new_tempo ) } } - -NotePlayHandle ** NotePlayHandleManager::s_available; -QReadWriteLock NotePlayHandleManager::s_mutex; -std::atomic_int NotePlayHandleManager::s_availableIndex; -int NotePlayHandleManager::s_size; - - -void NotePlayHandleManager::init() -{ - s_available = MM_ALLOC( NotePlayHandle*, INITIAL_NPH_CACHE ); - - NotePlayHandle * n = MM_ALLOC( NotePlayHandle, INITIAL_NPH_CACHE ); - - for( int i=0; i < INITIAL_NPH_CACHE; ++i ) - { - s_available[ i ] = n; - ++n; - } - s_availableIndex = INITIAL_NPH_CACHE - 1; - s_size = INITIAL_NPH_CACHE; -} - - -NotePlayHandle * NotePlayHandleManager::acquire( InstrumentTrack* instrumentTrack, - const f_cnt_t offset, - const f_cnt_t frames, - const Note& noteToPlay, - NotePlayHandle* parent, - int midiEventChannel, - NotePlayHandle::Origin origin ) -{ - // TODO: use some lockless data structures - s_mutex.lockForWrite(); - if (s_availableIndex < 0) { extend(NPH_CACHE_INCREMENT); } - NotePlayHandle * nph = s_available[s_availableIndex--]; - s_mutex.unlock(); - - new( (void*)nph ) NotePlayHandle( instrumentTrack, offset, frames, noteToPlay, parent, midiEventChannel, origin ); - return nph; -} - - -void NotePlayHandleManager::release( NotePlayHandle * nph ) -{ - nph->NotePlayHandle::~NotePlayHandle(); - s_mutex.lockForRead(); - s_available[++s_availableIndex] = nph; - s_mutex.unlock(); -} - - -void NotePlayHandleManager::extend( int c ) -{ - s_size += c; - NotePlayHandle ** tmp = MM_ALLOC( NotePlayHandle*, s_size ); - MM_FREE( s_available ); - s_available = tmp; - - NotePlayHandle * n = MM_ALLOC( NotePlayHandle, c ); - - for( int i=0; i < c; ++i ) - { - s_available[++s_availableIndex] = n; - ++n; - } -} +const int INITIAL_NPH_CACHE = 256; +MemoryPool NotePlayHandlePool{INITIAL_NPH_CACHE}; diff --git a/src/core/PresetPreviewPlayHandle.cpp b/src/core/PresetPreviewPlayHandle.cpp index ca0e5219499..afb5a029c73 100644 --- a/src/core/PresetPreviewPlayHandle.cpp +++ b/src/core/PresetPreviewPlayHandle.cpp @@ -182,7 +182,7 @@ PresetPreviewPlayHandle::PresetPreviewPlayHandle( const QString & _preset_file, Engine::mixer()->requestChangeInModel(); // create note-play-handle for it - m_previewNote = NotePlayHandleManager::acquire( + m_previewNote = NotePlayHandlePool.construct( s_previewTC->previewInstrumentTrack(), 0, typeInfo::max() / 2, Note( 0, 0, DefaultKey, 100 ) ); diff --git a/src/core/main.cpp b/src/core/main.cpp index f579ec8f694..1c4ba94affb 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -286,9 +286,6 @@ int main( int argc, char * * argv ) qInstallMessageHandler(consoleMessageHandler); #endif - // initialize memory managers - NotePlayHandleManager::init(); - // intialize RNG srand( getpid() + time( 0 ) ); diff --git a/src/tracks/InstrumentTrack.cpp b/src/tracks/InstrumentTrack.cpp index 730ab97bd1e..18c73d49a25 100644 --- a/src/tracks/InstrumentTrack.cpp +++ b/src/tracks/InstrumentTrack.cpp @@ -261,11 +261,11 @@ void InstrumentTrack::processInEvent( const MidiEvent& event, const MidiTime& ti if( m_notes[event.key()] == NULL ) { NotePlayHandle* nph = - NotePlayHandleManager::acquire( + NotePlayHandlePool.construct( this, offset, typeInfo::max() / 2, Note( MidiTime(), MidiTime(), event.key(), event.volume( midiPort()->baseVelocity() ) ), - NULL, event.channel(), + nullptr, event.channel(), NotePlayHandle::OriginMidiInput ); m_notes[event.key()] = nph; if( ! Engine::mixer()->addPlayHandle( nph ) ) @@ -691,7 +691,7 @@ bool InstrumentTrack::play( const MidiTime & _start, const fpp_t _frames, const f_cnt_t note_frames = cur_note->length().frames( frames_per_tick ); - NotePlayHandle* notePlayHandle = NotePlayHandleManager::acquire( this, _offset, note_frames, *cur_note ); + NotePlayHandle* notePlayHandle = NotePlayHandlePool.construct( this, _offset, note_frames, *cur_note ); notePlayHandle->setBBTrack( bb_track ); // are we playing global song? if( _tco_num < 0 ) From 178888af9436aeef7bdac00c7e744a868dd7ce67 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 17 Apr 2018 16:53:22 +0200 Subject: [PATCH 06/28] BufferManager: Use MemoryPool, rename to BufferPool --- include/{BufferManager.h => BufferPool.h} | 10 +++--- plugins/vestige/vestige.cpp | 2 -- .../{BufferManager.cpp => BufferPool.cpp} | 32 +++++++++---------- src/core/CMakeLists.txt | 2 +- src/core/FxMixer.cpp | 8 ++--- src/core/Mixer.cpp | 13 ++++---- src/core/Oscillator.cpp | 4 +-- src/core/PlayHandle.cpp | 8 ++--- src/core/RemotePlugin.cpp | 8 ++--- src/core/audio/AudioPort.cpp | 8 ++--- src/gui/widgets/VisualizationWidget.cpp | 4 +-- 11 files changed, 46 insertions(+), 53 deletions(-) rename include/{BufferManager.h => BufferPool.h} (90%) rename src/core/{BufferManager.cpp => BufferPool.cpp} (62%) diff --git a/include/BufferManager.h b/include/BufferPool.h similarity index 90% rename from include/BufferManager.h rename to include/BufferPool.h index 20390644b95..6d5cd08e2b4 100644 --- a/include/BufferManager.h +++ b/include/BufferPool.h @@ -1,5 +1,5 @@ /* - * BufferManager.h - A buffer caching/memory management system + * BufferPool.h * * Copyright (c) 2014 Vesa Kivimäki * Copyright (c) 2006-2014 Tobias Doerffel @@ -23,13 +23,13 @@ * */ -#ifndef BUFFER_MANAGER_H -#define BUFFER_MANAGER_H +#pragma once #include "lmms_export.h" #include "lmms_basics.h" -class LMMS_EXPORT BufferManager +/// Legacy interface for buffer re-use. Uses MemoryPool internally now. +class LMMS_EXPORT BufferPool { public: static void init( fpp_t framesPerPeriod ); @@ -43,5 +43,3 @@ class LMMS_EXPORT BufferManager #endif static void release( sampleFrame * buf ); }; - -#endif diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index fc61a248441..31f359e2a02 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -38,8 +38,6 @@ #include #include -#include "ConfigManager.h" -#include "BufferManager.h" #include "ConfigManager.h" #include "Engine.h" #include "gui_templates.h" diff --git a/src/core/BufferManager.cpp b/src/core/BufferPool.cpp similarity index 62% rename from src/core/BufferManager.cpp rename to src/core/BufferPool.cpp index ed658866ca0..72dc60a5525 100644 --- a/src/core/BufferManager.cpp +++ b/src/core/BufferPool.cpp @@ -1,7 +1,7 @@ /* - * BufferManager.cpp - A buffer caching/memory management system + * BufferPool.cpp * - * Copyright (c) 2017 Lukas W + * Copyright (c) 2018 Lukas W * Copyright (c) 2014 Vesa Kivimäki * Copyright (c) 2006-2014 Tobias Doerffel * @@ -24,32 +24,31 @@ * */ -#include "BufferManager.h" +#include "BufferPool.h" -#include "Engine.h" -#include "Mixer.h" -#include "Memory.h" +#include +#include "MemoryPool.h" -static fpp_t framesPerPeriod; +static std::unique_ptr<_MemoryPool_Base> pool; +const int BM_INITIAL_BUFFERS = 256; -void BufferManager::init( fpp_t framesPerPeriod ) +void BufferPool::init( fpp_t framesPerPeriod ) { - ::framesPerPeriod = framesPerPeriod; + pool.reset(new _MemoryPool_Base(framesPerPeriod * sizeof(sampleFrame), BM_INITIAL_BUFFERS)); } - -sampleFrame * BufferManager::acquire() +sampleFrame * BufferPool::acquire() { - return MM_ALLOC( sampleFrame, ::framesPerPeriod ); + return reinterpret_cast(pool->allocate()); } -void BufferManager::clear( sampleFrame *ab, const f_cnt_t frames, const f_cnt_t offset ) +void BufferPool::clear( sampleFrame *ab, const f_cnt_t frames, const f_cnt_t offset ) { memset( ab + offset, 0, sizeof( *ab ) * frames ); } #ifndef LMMS_DISABLE_SURROUND -void BufferManager::clear( surroundSampleFrame * ab, const f_cnt_t frames, +void BufferPool::clear( surroundSampleFrame * ab, const f_cnt_t frames, const f_cnt_t offset ) { memset( ab + offset, 0, sizeof( *ab ) * frames ); @@ -57,8 +56,7 @@ void BufferManager::clear( surroundSampleFrame * ab, const f_cnt_t frames, #endif -void BufferManager::release( sampleFrame * buf ) +void BufferPool::release( sampleFrame * buf ) { - MM_FREE( buf ); + pool->deallocate(buf); } - diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4e8d7ef8a51..41124927282 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -5,7 +5,7 @@ set(LMMS_SRCS core/BandLimitedWave.cpp core/base64.cpp core/BBTrackContainer.cpp - core/BufferManager.cpp + core/BufferPool.cpp core/Clipboard.cpp core/ComboBoxModel.cpp core/ConfigManager.cpp diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 032090bf1d5..7d33e1af136 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -24,7 +24,7 @@ #include -#include "BufferManager.h" +#include "BufferPool.h" #include "FxMixer.h" #include "Mixer.h" #include "MixerWorkerThread.h" @@ -74,7 +74,7 @@ FxChannel::FxChannel( int idx, Model * _parent ) : m_queued( false ), m_dependenciesMet(0) { - BufferManager::clear( m_buffer, Engine::mixer()->framesPerPeriod() ); + BufferPool::clear( m_buffer, Engine::mixer()->framesPerPeriod() ); } @@ -585,7 +585,7 @@ void FxMixer::mixToChannel( const sampleFrame * _buf, fx_ch_t _ch ) void FxMixer::prepareMasterMix() { - BufferManager::clear( m_fxChannels[0]->m_buffer, + BufferPool::clear( m_fxChannels[0]->m_buffer, Engine::mixer()->framesPerPeriod() ); } @@ -658,7 +658,7 @@ void FxMixer::masterMix( sampleFrame * _buf ) // reset channel process state for( int i = 0; i < numChannels(); ++i) { - BufferManager::clear( m_fxChannels[i]->m_buffer, + BufferPool::clear( m_fxChannels[i]->m_buffer, Engine::mixer()->framesPerPeriod() ); m_fxChannels[i]->reset(); m_fxChannels[i]->m_queued = false; diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 8ad36c73bb7..1cf0635696e 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -37,6 +37,7 @@ #include "ConfigManager.h" #include "SamplePlayHandle.h" #include "Memory.h" +#include "BufferPool.h" // platform-specific audio-interface-classes #include "AudioAlsa.h" @@ -59,8 +60,6 @@ #include "MidiApple.h" #include "MidiDummy.h" -#include "BufferManager.h" - typedef LocklessList::Element LocklessListElement; @@ -98,7 +97,7 @@ Mixer::Mixer( bool renderOnly ) : m_inputBufferFrames[i] = 0; m_inputBufferSize[i] = DEFAULT_BUFFER_SIZE * 100; m_inputBuffer[i] = new sampleFrame[ DEFAULT_BUFFER_SIZE * 100 ]; - BufferManager::clear( m_inputBuffer[i], m_inputBufferSize[i] ); + BufferPool::clear( m_inputBuffer[i], m_inputBufferSize[i] ); } // determine FIFO size and number of frames per period @@ -133,15 +132,15 @@ Mixer::Mixer( bool renderOnly ) : // allocte the FIFO from the determined size m_fifo = new fifo( fifoSize ); - // now that framesPerPeriod is fixed initialize global BufferManager - BufferManager::init( m_framesPerPeriod ); + // now that framesPerPeriod is fixed initialize global BufferPool + BufferPool::init( m_framesPerPeriod ); AlignedAllocator alloc; for( int i = 0; i < 3; i++ ) { m_readBuf = alloc.allocate( m_framesPerPeriod ); - BufferManager::clear( m_readBuf, m_framesPerPeriod ); + BufferPool::clear( m_readBuf, m_framesPerPeriod ); m_bufferPool.push_back( m_readBuf ); } @@ -417,7 +416,7 @@ const surroundSampleFrame * Mixer::renderNextBuffer() m_readBuf = m_bufferPool[m_readBuffer]; // clear last audio-buffer - BufferManager::clear( m_writeBuf, m_framesPerPeriod ); + BufferPool::clear( m_writeBuf, m_framesPerPeriod ); // prepare master mix (clear internal buffers etc.) FxMixer * fxMixer = Engine::fxMixer(); diff --git a/src/core/Oscillator.cpp b/src/core/Oscillator.cpp index b7dc5bff535..bb06d98042c 100644 --- a/src/core/Oscillator.cpp +++ b/src/core/Oscillator.cpp @@ -24,7 +24,7 @@ #include "Oscillator.h" -#include "BufferManager.h" +#include "BufferPool.h" #include "Engine.h" #include "Mixer.h" #include "AutomatableModel.h" @@ -59,7 +59,7 @@ void Oscillator::update( sampleFrame * _ab, const fpp_t _frames, { if( m_freq >= Engine::mixer()->processingSampleRate() / 2 ) { - BufferManager::clear( _ab, _frames ); + BufferPool::clear( _ab, _frames ); return; } if( m_subOsc != NULL ) diff --git a/src/core/PlayHandle.cpp b/src/core/PlayHandle.cpp index 9e92019a6b6..67ddb5e354f 100644 --- a/src/core/PlayHandle.cpp +++ b/src/core/PlayHandle.cpp @@ -23,7 +23,7 @@ */ #include "PlayHandle.h" -#include "BufferManager.h" +#include "BufferPool.h" #include "Engine.h" #include "Mixer.h" @@ -36,7 +36,7 @@ PlayHandle::PlayHandle(const Type type, f_cnt_t offset) : m_type(type), m_offset(offset), m_affinity(QThread::currentThread()), - m_playHandleBuffer(BufferManager::acquire()), + m_playHandleBuffer(BufferPool::acquire()), m_bufferReleased(true), m_usesBuffer(true) { @@ -45,7 +45,7 @@ PlayHandle::PlayHandle(const Type type, f_cnt_t offset) : PlayHandle::~PlayHandle() { - BufferManager::release(m_playHandleBuffer); + BufferPool::release(m_playHandleBuffer); } @@ -54,7 +54,7 @@ void PlayHandle::doProcessing() if( m_usesBuffer ) { m_bufferReleased = false; - BufferManager::clear(m_playHandleBuffer, Engine::mixer()->framesPerPeriod()); + BufferPool::clear(m_playHandleBuffer, Engine::mixer()->framesPerPeriod()); play( buffer() ); } else diff --git a/src/core/RemotePlugin.cpp b/src/core/RemotePlugin.cpp index 23654d782ac..82bec26719e 100644 --- a/src/core/RemotePlugin.cpp +++ b/src/core/RemotePlugin.cpp @@ -28,7 +28,7 @@ #include #endif -#include "BufferManager.h" +#include "BufferPool.h" #include "RemotePlugin.h" #include "Mixer.h" #include "Engine.h" @@ -287,7 +287,7 @@ bool RemotePlugin::process( const sampleFrame * _in_buf, { if( _out_buf != NULL ) { - BufferManager::clear( _out_buf, frames ); + BufferPool::clear( _out_buf, frames ); } return false; } @@ -306,7 +306,7 @@ bool RemotePlugin::process( const sampleFrame * _in_buf, } if( _out_buf != NULL ) { - BufferManager::clear( _out_buf, frames ); + BufferPool::clear( _out_buf, frames ); } return false; } @@ -380,7 +380,7 @@ bool RemotePlugin::process( const sampleFrame * _in_buf, sampleFrame * o = (sampleFrame *) ( m_shm + m_inputCount*frames ); // clear buffer, if plugin didn't fill up both channels - BufferManager::clear( _out_buf, frames ); + BufferPool::clear( _out_buf, frames ); for( ch_cnt_t ch = 0; ch < qMin( DEFAULT_CHANNELS, outputs ); ++ch ) diff --git a/src/core/audio/AudioPort.cpp b/src/core/audio/AudioPort.cpp index 71544dde2d5..91bd2d9d97d 100644 --- a/src/core/audio/AudioPort.cpp +++ b/src/core/audio/AudioPort.cpp @@ -29,14 +29,14 @@ #include "Engine.h" #include "Mixer.h" #include "MixHelpers.h" -#include "BufferManager.h" +#include "BufferPool.h" AudioPort::AudioPort( const QString & _name, bool _has_effect_chain, FloatModel * volumeModel, FloatModel * panningModel, BoolModel * mutedModel ) : m_bufferUsage( false ), - m_portBuffer( BufferManager::acquire() ), + m_portBuffer( BufferPool::acquire() ), m_extOutputEnabled( false ), m_nextFxChannel( 0 ), m_name( "unnamed port" ), @@ -56,7 +56,7 @@ AudioPort::~AudioPort() { setExtOutputEnabled( false ); Engine::mixer()->removeAudioPort( this ); - BufferManager::release( m_portBuffer ); + BufferPool::release( m_portBuffer ); } @@ -111,7 +111,7 @@ void AudioPort::doProcessing() const fpp_t fpp = Engine::mixer()->framesPerPeriod(); // clear the buffer - BufferManager::clear( m_portBuffer, fpp ); + BufferPool::clear( m_portBuffer, fpp ); //qDebug( "Playhandles: %d", m_playHandles.size() ); for( PlayHandle * ph : m_playHandles ) // now we mix all playhandle buffers into the audioport buffer diff --git a/src/gui/widgets/VisualizationWidget.cpp b/src/gui/widgets/VisualizationWidget.cpp index 7234331dfd6..2d933ec8072 100644 --- a/src/gui/widgets/VisualizationWidget.cpp +++ b/src/gui/widgets/VisualizationWidget.cpp @@ -35,7 +35,7 @@ #include "ToolTip.h" #include "Song.h" -#include "BufferManager.h" +#include "BufferPool.h" VisualizationWidget::VisualizationWidget( const QPixmap & _bg, QWidget * _p, @@ -55,7 +55,7 @@ VisualizationWidget::VisualizationWidget( const QPixmap & _bg, QWidget * _p, const fpp_t frames = Engine::mixer()->framesPerPeriod(); m_buffer = new sampleFrame[frames]; - BufferManager::clear( m_buffer, frames ); + BufferPool::clear( m_buffer, frames ); ToolTip::add( this, tr( "Oscilloscope" ) ); From 2cb4455a5f2c1a63bc341cc29b6922ba7311f3cc Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 18 Apr 2018 08:12:56 +0200 Subject: [PATCH 07/28] Replace AllignedAllocator implementation with rpmalloc calls --- include/Memory.h | 4 ++-- src/core/Memory.cpp | 24 +++--------------------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/include/Memory.h b/include/Memory.h index f4cc126e078..791d45c204c 100644 --- a/include/Memory.h +++ b/include/Memory.h @@ -81,7 +81,7 @@ class MmAllocator class _AlignedAllocator_Base { protected: - void* alloc_impl( size_t n, size_t alignment ); + void* alloc_impl( size_t alignment, size_t size ); void dealloc_impl( void* p ); }; @@ -97,7 +97,7 @@ class AlignedAllocator : _AlignedAllocator_Base T* allocate( std::size_t n ) { - return reinterpret_cast( alloc_impl( sizeof(T) * n, alignment ) ); + return reinterpret_cast( alloc_impl( alignment, sizeof(T) * n ) ); } void deallocate( T* p, std::size_t ) diff --git a/src/core/Memory.cpp b/src/core/Memory.cpp index 9f3df1f079a..bd8b1ca80c6 100644 --- a/src/core/Memory.cpp +++ b/src/core/Memory.cpp @@ -69,30 +69,12 @@ void MemoryManager::thread_deinitialize() rpmalloc_thread_finalize(); } -void* _AlignedAllocator_Base::alloc_impl( size_t n , size_t alignment) +void* _AlignedAllocator_Base::alloc_impl(size_t alignment, size_t size ) { - char *ptr, *ptr2, *aligned_ptr; - int align_mask = alignment - 1; - - ptr = static_cast( malloc( n + alignment + sizeof( int ) ) ); - - if( ptr == NULL ) throw std::bad_alloc{}; - - ptr2 = ptr + sizeof( int ); - aligned_ptr = ptr2 + ( alignment - ( ( size_t ) ptr2 & align_mask ) ); - - ptr2 = aligned_ptr - sizeof( int ); - *( ( int* ) ptr2 ) = ( int )( aligned_ptr - ptr ); - - return aligned_ptr; + return rpaligned_alloc(alignment, size); } void _AlignedAllocator_Base::dealloc_impl(void* p) { - if ( !p ) return; - - int *ptr2 = static_cast( p ) - 1; - p = static_cast( p ) - *ptr2; - free( p ); + rpfree(p); } - From ef7b8c68d52fcb0d8efa378fa00b9ebb11c474d5 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 18 Apr 2018 08:18:23 +0200 Subject: [PATCH 08/28] Add naive benchmarks --- CMakeLists.txt | 2 + benchmarks/CMakeLists.txt | 15 +++++ benchmarks/benchmark.cpp | 130 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+) create mode 100644 benchmarks/CMakeLists.txt create mode 100644 benchmarks/benchmark.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bd9d376e286..387b926d7a2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,6 +140,7 @@ CHECK_INCLUDE_FILES(locale.h LMMS_HAVE_LOCALE_H) LIST(APPEND CMAKE_PREFIX_PATH "${CMAKE_INSTALL_PREFIX}") + FIND_PACKAGE(Qt5 COMPONENTS Core Gui Widgets Xml REQUIRED) FIND_PACKAGE(Qt5 COMPONENTS LinguistTools QUIET) @@ -561,6 +562,7 @@ include(CompileCache) ADD_SUBDIRECTORY(cmake) ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(plugins) +ADD_SUBDIRECTORY(benchmarks) ADD_SUBDIRECTORY(tests) ADD_SUBDIRECTORY(data) ADD_SUBDIRECTORY(doc) diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt new file mode 100644 index 00000000000..49cc4ee2f06 --- /dev/null +++ b/benchmarks/CMakeLists.txt @@ -0,0 +1,15 @@ +INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}") +INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}") +INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include") +INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}") + +SET(CMAKE_CXX_STANDARD 11) + +SET(CMAKE_AUTOMOC ON) + +ADD_EXECUTABLE(benchmarks + EXCLUDE_FROM_ALL + benchmark.cpp + $ +) +TARGET_LINK_LIBRARIES(benchmarks ${QT_LIBRARIES} ${LMMS_REQUIRED_LIBS}) diff --git a/benchmarks/benchmark.cpp b/benchmarks/benchmark.cpp new file mode 100644 index 00000000000..da4af8f88b8 --- /dev/null +++ b/benchmarks/benchmark.cpp @@ -0,0 +1,130 @@ +#include + +#include +#include + +#include "libcds.h" +#include + +#include "Engine.h" +#include "PerfLog.h" + +#include "LocklessList.h" +#include "MemoryPool.h" + +#include "NotePlayHandle.h" + +template +using LocklessQueue = cds::container::VyukovMPMCCycleQueue; + +template +void benchmark_allocator(QString name, Alloc&& alloc, size_t n, size_t I) +{ + using T = typename Alloc::value_type; + constexpr size_t S = sizeof(T); + + std::vector ptrs{n}; + PerfLogTimer timer(QString("Allocate: %1 x %2 x %3 bytes, %4") + .arg(I).arg(n).arg(S).arg(name)); + + for (size_t i=0; i < I; i++) + { + for (size_t j=0; j < n; j++) { + ptrs[j] = alloc.allocate(1); + } + for (size_t j=0; j < n; j++) { + alloc.deallocate(ptrs[j], 1); + } + } +} + + +template +void benchmark_allocator_threaded(QString name, Alloc&& alloc, size_t n, size_t t) +{ + using T = typename Alloc::value_type; + constexpr size_t S = sizeof(T); + + LocklessQueue ptrs{n}; + + PerfLogTimer timer(QString("Allocate multi-threaded: %1 x %2 bytes using %3 threads, %4") + .arg(n).arg(S).arg(t).arg(name)); + + std::vector threads; threads.reserve(t*2); + + std::atomic_uint_fast64_t allocated{0}; + std::atomic_uint_fast64_t deallocated{0}; + + for (size_t i=0; i < t; i++) { + threads.emplace_back([&]() { + while(allocated++ < n) { + auto ptr = alloc.allocate(1); + ptrs.push(ptr); + } + }); + } + for (size_t i=0; i < t; i++) { + threads.emplace_back([&]() { + while(deallocated++ < n) { + T* ptr; + while (! ptrs.pop(ptr)); + alloc.deallocate(ptr, 1); + } + }); + } + + for (std::thread& thread : threads) { + thread.join(); + } +} + +int main(int argc, char* argv[]) +{ + new QCoreApplication(argc, argv); + + using Stack = LocklessList; + { + size_t n = 100 * 1000 * 1000; + Stack stack{n}; + PerfLogTimer timer("LocklessList: Insert 100m entries, single-threaded, pre-allocated"); + for (size_t i=0; i < n; i++) { + stack.push(i); + } + } + { + size_t n = 50 * 1000 * 1000; + size_t t = 5; + Stack stack{n}; + std::vector threads; threads.reserve(t); + PerfLogTimer timer("LocklessList: Push 50m entries, multi-threaded, pre-allocated"); + + for (int i=0; i < 5; i++) { + threads.emplace_back([&]() { + for (size_t j=0; j < n / t; j++) { + stack.push(j); + } + }); + } + + for (int i=0; i < 5; i++) { + threads.at(i).join(); + } + } + + { + size_t n = 10 * 1000 * 1000; + constexpr size_t S = 256; + using T = std::array; + benchmark_allocator("std::allocator", std::allocator{}, n, 1); + benchmark_allocator("MmAllocator", MmAllocator{}, n, 1); + benchmark_allocator("MemoryPool", MemoryPool{n}, n, 1); + } + { + size_t n = 10 * 1000 * 1000; + constexpr size_t S = 256; + using T = std::array; + benchmark_allocator_threaded("std::allocator", std::allocator{}, n, 4); + benchmark_allocator_threaded("MmAllocator", MmAllocator{}, n, 4); + benchmark_allocator_threaded("MemoryPool", MemoryPool{n}, n, 4); + } +} From 8b122d5a4c4aefc1538e8c420cd18d6343b795a2 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sun, 29 Apr 2018 19:34:14 +0200 Subject: [PATCH 09/28] Fix libcds on MinGW --- CMakeLists.txt | 2 + cmake/modules/DetectMachine.cmake | 26 ++++++++++ .../toolchains/common/Ubuntu-MinGW-W64.cmake | 5 +- include/libcds.h | 7 +++ include/mingw-std-threads/mutex | 1 + include/mingw-std-threads/thread | 1 + plugins/CMakeLists.txt | 7 +++ src/3rdparty/CMakeLists.txt | 51 ++++++++++++++++++- src/CMakeLists.txt | 2 +- src/core/MemoryPool.cpp | 8 +-- 10 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 include/mingw-std-threads/mutex create mode 100644 include/mingw-std-threads/thread diff --git a/CMakeLists.txt b/CMakeLists.txt index 387b926d7a2..5773da89105 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,6 +151,8 @@ INCLUDE_DIRECTORIES( ${Qt5Xml_INCLUDE_DIRS} ) +INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/src/3rdparty/mingw-std-threads") + SET(QT_LIBRARIES Qt5::Core Qt5::Gui diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake index f3458165b3d..c4ab3e51669 100644 --- a/cmake/modules/DetectMachine.cmake +++ b/cmake/modules/DetectMachine.cmake @@ -1,3 +1,5 @@ +INCLUDE(CheckCXXSourceCompiles) + IF(WIN32) SET(LMMS_BUILD_WIN32 1) ELSEIF(APPLE) @@ -86,3 +88,27 @@ IF(LMMS_BUILD_APPLE) STRING(REGEX REPLACE "\\.[0-9]*$" "" APPLE_OS_VER "${APPLE_OS_VER}") SET(CMAKE_MACOSX_RPATH 1) ENDIF() + +# Detect MinGW +IF(WIN32 AND CMAKE_COMPILER_IS_GNUCXX) + SET(MINGW TRUE) +ENDIF() + +# Detect MINGW thread support +IF(MINGW) + CHECK_CXX_SOURCE_COMPILES(" + #include + #include + int main(int argc, const char* argv[]) { + std::mutex m; + std::this_thread::yield(); + return 0; + } + " HAS_STD_THREADS) + IF(NOT HAS_STD_THREADS) + SET(NEED_MINGW_THREADS_REPLACEMENT TRUE) + ELSE() + SET(NEED_MINGW_THREADS_REPLACEMENT FALSE) + ENDIF() + MESSAGE(NEED_MINGW_THREADS_REPLACEMENT ${NEED_MINGW_THREADS_REPLACEMENT}) +ENDIF() diff --git a/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake b/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake index 2f78a441e7a..bd68a89be03 100644 --- a/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake +++ b/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake @@ -5,13 +5,16 @@ set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) -set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) +set(MINGW_PREFIX /usr/${TOOLCHAIN_PREFIX}) + +set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX}) SET(ENV{PKG_CONFIG} /usr/bin/${TOOLCHAIN_PREFIX}-pkg-config) IF(WIN64) SET(TOOLCHAIN_PREFIX32 ${CMAKE_SYSTEM_PROCESSOR32}-w64-mingw32) SET(CMAKE_C_COMPILER32 ${TOOLCHAIN_PREFIX32}-gcc) SET(CMAKE_CXX_COMPILER32 ${TOOLCHAIN_PREFIX32}-g++) + set(MINGW_PREFIX32 /usr/${TOOLCHAIN_PREFIX32}) ENDIF() INCLUDE(${CMAKE_CURRENT_LIST_DIR}/WinCrossCompile.cmake) diff --git a/include/libcds.h b/include/libcds.h index 0d095d03cce..7acbabea7da 100644 --- a/include/libcds.h +++ b/include/libcds.h @@ -1,7 +1,14 @@ #pragma once +#include + #include "NiftyCounter.h" +#if defined(__MINGW32__) && !defined(_GLIBCXX_HAS_GTHREADS) +# include "mingw-std-threads/thread" +# include "mingw-std-threads/mutex" +#endif + namespace _cdslib { void init(); diff --git a/include/mingw-std-threads/mutex b/include/mingw-std-threads/mutex new file mode 100644 index 00000000000..afeaf55b138 --- /dev/null +++ b/include/mingw-std-threads/mutex @@ -0,0 +1 @@ +#include "mingw.mutex.h" diff --git a/include/mingw-std-threads/thread b/include/mingw-std-threads/thread new file mode 100644 index 00000000000..0108f8ad70c --- /dev/null +++ b/include/mingw-std-threads/thread @@ -0,0 +1 @@ +#include "mingw.thread.h" diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 4f139f8b32b..fe8a5faa927 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -9,6 +9,13 @@ IF(LMMS_BUILD_APPLE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") ENDIF() +IF(MINGW_PREFIX) + # There's a bug in some CMake or MinGW versions that passes -std=c++11 when + # compiling C files (e.g. fmopl.c). Remove -Werror for plugins to work + # around this. + STRING(REPLACE "-Werror " "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) +ENDIF() + INCLUDE_DIRECTORIES( ${SAMPLERATE_INCLUDE_DIRS} "${CMAKE_BINARY_DIR}/src" diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index b2d73accc5c..5156cc4a180 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -11,4 +11,53 @@ ENDIF() ADD_SUBDIRECTORY(rpmalloc) ADD_SUBDIRECTORY(weakjack) -ADD_SUBDIRECTORY(libcds) +IF(WIN32 AND CMAKE_COMPILER_IS_GNUCXX) + SET(MINGW TRUE) +ENDIF() + +IF(MINGW) + # Work around linking errors with MinGW + SET(CDS_LIBRARY_TYPE SHARED) +ELSE() + SET(CDS_LIBRARY_TYPE STATIC) +ENDIF() + +ADD_LIBRARY(cds ${CDS_LIBRARY_TYPE} + libcds/src/init.cpp + libcds/src/hp.cpp + libcds/src/dhp.cpp + libcds/src/urcu_gp.cpp + libcds/src/urcu_sh.cpp + libcds/src/thread_data.cpp + libcds/src/topology_hpux.cpp + libcds/src/topology_linux.cpp + libcds/src/topology_osx.cpp + libcds/src/dllmain.cpp +) +SET_TARGET_PROPERTIES(cds PROPERTIES + CXX_STANDARD 11 + CXX_STANDARD_REQUIRED ON +) +TARGET_INCLUDE_DIRECTORIES(cds + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/libcds" +) + +IF(NEED_MINGW_THREADS_REPLACEMENT) + # Provide win32 threads implementation + TARGET_INCLUDE_DIRECTORIES(cds BEFORE + PRIVATE "${CMAKE_SOURCE_DIR}/include/mingw-std-threads" + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/mingw-std-threads" + ) +ENDIF() + +IF(CDS_LIBRARY_TYPE STREQUAL "STATIC") + TARGET_COMPILE_DEFINITIONS(cds + PRIVATE CDS_BUILD_STATIC_LIB + ) +ELSE() + TARGET_COMPILE_DEFINITIONS(cds + PRIVATE CDS_BUILD_LIB + ) + # Install DLL + install(TARGETS cds RUNTIME DESTINATION .) +ENDIF() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1cfe0e2087f..a49d3ed1e19 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -168,7 +168,7 @@ SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} ${SNDFILE_LIBRARIES} ${EXTRA_LIBRARIES} rpmalloc - cds-s + cds ) # Expose required libs for tests binary diff --git a/src/core/MemoryPool.cpp b/src/core/MemoryPool.cpp index a9cde2701d9..62dfad078c2 100644 --- a/src/core/MemoryPool.cpp +++ b/src/core/MemoryPool.cpp @@ -14,8 +14,8 @@ #include -#include #include "libcds.h" +#include #include "Memory.h" @@ -24,9 +24,9 @@ class _MemoryPool_Private : MmAllocator using Alloc = MmAllocator; public: _MemoryPool_Private(size_t size, size_t nmemb) - : m_freelist(nmemb) - , m_elementSize(size) + : m_elementSize(size) , m_numElms(nmemb) + , m_freelist(nmemb) { m_buffer = new char[m_elementSize * m_numElms]; for (size_t i = 0; i < m_numElms; i++) { @@ -67,7 +67,7 @@ class _MemoryPool_Private : MmAllocator { if (is_from_pool(ptr)) { bool pushed = m_freelist.push(reinterpret_cast(ptr)); - assert(pushed); + assert(pushed); Q_UNUSED(pushed); } else { do_deallocate(ptr); } From 2f8e231b8c3eee99e76d8d4db8c4071581d4138d Mon Sep 17 00:00:00 2001 From: Lukas W Date: Tue, 19 Jun 2018 20:35:55 +0200 Subject: [PATCH 10/28] Fix macOS linking problem --- cmake/modules/BuildPlugin.cmake | 30 ++++++++++-------------- plugins/LadspaEffect/calf/CMakeLists.txt | 2 ++ src/CMakeLists.txt | 13 ++++------ 3 files changed, 18 insertions(+), 27 deletions(-) diff --git a/cmake/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake index efa3e5b468e..40868966173 100644 --- a/cmake/modules/BuildPlugin.cmake +++ b/cmake/modules/BuildPlugin.cmake @@ -5,10 +5,14 @@ INCLUDE(GenQrc) -MACRO(BUILD_PLUGIN PLUGIN_NAME) - CMAKE_PARSE_ARGUMENTS(PLUGIN "" "LINK;EXPORT_BASE_NAME" "MOCFILES;EMBEDDED_RESOURCES;UICFILES" ${ARGN}) +FUNCTION(BUILD_PLUGIN PLUGIN_NAME) + CMAKE_PARSE_ARGUMENTS(PLUGIN "" "DESTINATION;LINK;EXPORT_BASE_NAME" "MOCFILES;EMBEDDED_RESOURCES;UICFILES" ${ARGN}) SET(PLUGIN_SOURCES ${PLUGIN_UNPARSED_ARGUMENTS}) + IF(NOT PLUGIN_DESTINATION) + SET(PLUGIN_DESTINATION "${PLUGIN_DIR}") + ENDIF() + INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/include") ADD_DEFINITIONS(-DPLUGIN_NAME=${PLUGIN_NAME}) @@ -56,22 +60,13 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) ADD_LIBRARY(${PLUGIN_NAME} ${PLUGIN_LINK} ${PLUGIN_SOURCES} ${plugin_MOC_out} ${RCC_OUT}) - TARGET_LINK_LIBRARIES(${PLUGIN_NAME} Qt5::Widgets Qt5::Xml) - - IF(LMMS_BUILD_WIN32) - TARGET_LINK_LIBRARIES(${PLUGIN_NAME} lmms) - ENDIF(LMMS_BUILD_WIN32) + TARGET_LINK_LIBRARIES(${PLUGIN_NAME} Qt5::Widgets Qt5::Xml lmms) - INSTALL(TARGETS ${PLUGIN_NAME} DESTINATION "${PLUGIN_DIR}") + INSTALL(TARGETS ${PLUGIN_NAME} DESTINATION "${PLUGIN_DESTINATION}") - IF(LMMS_BUILD_APPLE) - IF ("${PLUGIN_LINK}" STREQUAL "SHARED") - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") - ELSE() - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LINK_FLAGS "-bundle_loader \"${CMAKE_BINARY_DIR}/lmms\"") - ENDIF() - ADD_DEPENDENCIES(${PLUGIN_NAME} lmms) - ENDIF(LMMS_BUILD_APPLE) + IF(LMMS_BUILD_APPLE AND "${PLUGIN_LINK}" STREQUAL "SHARED") + SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") + ENDIF() IF(LMMS_BUILD_WIN32 AND STRIP) SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES PREFIX "") ADD_CUSTOM_COMMAND(TARGET ${PLUGIN_NAME} POST_BUILD COMMAND ${STRIP} "$") @@ -89,5 +84,4 @@ MACRO(BUILD_PLUGIN PLUGIN_NAME) TARGET_INCLUDE_DIRECTORIES(${PLUGIN_NAME} PUBLIC $ ) -ENDMACRO(BUILD_PLUGIN) - +ENDFUNCTION(BUILD_PLUGIN) diff --git a/plugins/LadspaEffect/calf/CMakeLists.txt b/plugins/LadspaEffect/calf/CMakeLists.txt index 4924169e410..58a40d99fbc 100644 --- a/plugins/LadspaEffect/calf/CMakeLists.txt +++ b/plugins/LadspaEffect/calf/CMakeLists.txt @@ -49,3 +49,5 @@ ENDIF() IF(NOT LMMS_BUILD_APPLE AND NOT LMMS_BUILD_OPENBSD) SET_TARGET_PROPERTIES(veal PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined") ENDIF() + +TARGET_LINK_LIBRARIES(veal lmms) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a49d3ed1e19..f8cfa3c030d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -188,12 +188,15 @@ FOREACH(LIB ${LMMS_REQUIRED_LIBS}) ENDFOREACH() +SET_TARGET_PROPERTIES(lmms PROPERTIES + ENABLE_EXPORTS ON +) + # Install IF(NOT MSVC) IF(LMMS_BUILD_WIN32) SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -mwindows" - ENABLE_EXPORTS ON ) IF(LMMS_BUILD_MSYS) @@ -276,23 +279,15 @@ IF(NOT MSVC) ENDIF() ELSE(LMMS_BUILD_WIN32) - IF(NOT LMMS_BUILD_APPLE) - SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E") - ENDIF(NOT LMMS_BUILD_APPLE) - INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") INSTALL(FILES "${CMAKE_BINARY_DIR}/lmms.1.gz" DESTINATION "${CMAKE_INSTALL_PREFIX}/share/man/man1/" PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) ENDIF(LMMS_BUILD_WIN32) ELSE(NOT MSVC) - SET_TARGET_PROPERTIES(lmms PROPERTIES - ENABLE_EXPORTS ON - ) INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -mwindows" - ENABLE_EXPORTS ON ) #CMAKE_FIND_ROOT_PATH From 119efeec01edd736296f753e9c3bd0220b21d76b Mon Sep 17 00:00:00 2001 From: Lukas W Date: Thu, 21 Jun 2018 13:31:51 +0200 Subject: [PATCH 11/28] Fix tests crash due to incomplete cleanup --- tests/main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/main.cpp b/tests/main.cpp index 7b07778fc16..2cf71aaa52d 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -19,5 +19,7 @@ int main(int argc, char* argv[]) failed += QTest::qExec(suite, argc, argv); } qDebug() << "<<" << failed << "out of"< Date: Sun, 8 Jul 2018 14:30:13 +0200 Subject: [PATCH 12/28] Memory: Fix wrong rebind --- include/Memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/Memory.h b/include/Memory.h index 791d45c204c..243d1e47657 100644 --- a/include/Memory.h +++ b/include/Memory.h @@ -90,7 +90,7 @@ class AlignedAllocator : _AlignedAllocator_Base { public: typedef T value_type; - template struct rebind { typedef MmAllocator other; }; + template struct rebind { typedef AlignedAllocator other; }; AlignedAllocator( size_t alignment = 16 ) : alignment(alignment) {} From 5349be6a63575a6409333f6425fe59b2c0852899 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Fri, 3 Aug 2018 13:13:15 +0200 Subject: [PATCH 13/28] NiftyCounter: Fix decrement --- include/NiftyCounter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/NiftyCounter.h b/include/NiftyCounter.h index 75128e40ee4..3b333c58f3f 100644 --- a/include/NiftyCounter.h +++ b/include/NiftyCounter.h @@ -37,7 +37,7 @@ template class _NiftyCounterCD_Base : public _N static void init() { C(); } static void deinit() { D(); } static int inc() { return T::s_count++; } - static int dec() { return T::s_count--; } + static int dec() { return --T::s_count; } }; From d35df8ee7b4dfd23bd748485cd271face09afe5f Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sun, 25 Aug 2019 23:47:03 +0200 Subject: [PATCH 14/28] Move BufferPool::clear to MixHelpers and rewrite * Move out of BufferPool because it's not related to memory allocation * Rewrite because memset() is not portable because it sets all bytes to zero which depends on the platform's float representation of 0.0 to be all zero bytes --- include/BufferPool.h | 7 ------- include/MixHelpers.h | 5 +++++ src/core/BufferPool.cpp | 14 -------------- src/core/FxMixer.cpp | 6 +++--- src/core/MixHelpers.cpp | 16 ++++++++++++++++ src/core/Mixer.cpp | 7 ++++--- src/core/Oscillator.cpp | 4 ++-- src/core/PlayHandle.cpp | 5 +++-- src/core/RemotePlugin.cpp | 8 ++++---- src/core/audio/AudioPort.cpp | 2 +- src/gui/widgets/VisualizationWidget.cpp | 4 ++-- 11 files changed, 40 insertions(+), 38 deletions(-) diff --git a/include/BufferPool.h b/include/BufferPool.h index 6d5cd08e2b4..9a552faaec9 100644 --- a/include/BufferPool.h +++ b/include/BufferPool.h @@ -34,12 +34,5 @@ class LMMS_EXPORT BufferPool public: static void init( fpp_t framesPerPeriod ); static sampleFrame * acquire(); - // audio-buffer-mgm - static void clear( sampleFrame * ab, const f_cnt_t frames, - const f_cnt_t offset = 0 ); -#ifndef LMMS_DISABLE_SURROUND - static void clear( surroundSampleFrame * ab, const f_cnt_t frames, - const f_cnt_t offset = 0 ); -#endif static void release( sampleFrame * buf ); }; diff --git a/include/MixHelpers.h b/include/MixHelpers.h index 872319f82df..2bef776c561 100644 --- a/include/MixHelpers.h +++ b/include/MixHelpers.h @@ -37,6 +37,11 @@ bool useNaNHandler(); void setNaNHandler( bool use ); +void clear(sampleFrame * src, int frames); +#ifndef LMMS_DISABLE_SURROUND +void clear(surroundSampleFrame * src, int frames); +#endif + bool sanitize( sampleFrame * src, int frames ); /*! \brief Add samples from src to dst */ diff --git a/src/core/BufferPool.cpp b/src/core/BufferPool.cpp index 72dc60a5525..4e52e382604 100644 --- a/src/core/BufferPool.cpp +++ b/src/core/BufferPool.cpp @@ -42,20 +42,6 @@ sampleFrame * BufferPool::acquire() return reinterpret_cast(pool->allocate()); } -void BufferPool::clear( sampleFrame *ab, const f_cnt_t frames, const f_cnt_t offset ) -{ - memset( ab + offset, 0, sizeof( *ab ) * frames ); -} - -#ifndef LMMS_DISABLE_SURROUND -void BufferPool::clear( surroundSampleFrame * ab, const f_cnt_t frames, - const f_cnt_t offset ) -{ - memset( ab + offset, 0, sizeof( *ab ) * frames ); -} -#endif - - void BufferPool::release( sampleFrame * buf ) { pool->deallocate(buf); diff --git a/src/core/FxMixer.cpp b/src/core/FxMixer.cpp index 7d33e1af136..4eb44ab8945 100644 --- a/src/core/FxMixer.cpp +++ b/src/core/FxMixer.cpp @@ -74,7 +74,7 @@ FxChannel::FxChannel( int idx, Model * _parent ) : m_queued( false ), m_dependenciesMet(0) { - BufferPool::clear( m_buffer, Engine::mixer()->framesPerPeriod() ); + MixHelpers::clear( m_buffer, Engine::mixer()->framesPerPeriod() ); } @@ -585,7 +585,7 @@ void FxMixer::mixToChannel( const sampleFrame * _buf, fx_ch_t _ch ) void FxMixer::prepareMasterMix() { - BufferPool::clear( m_fxChannels[0]->m_buffer, + MixHelpers::clear( m_fxChannels[0]->m_buffer, Engine::mixer()->framesPerPeriod() ); } @@ -658,7 +658,7 @@ void FxMixer::masterMix( sampleFrame * _buf ) // reset channel process state for( int i = 0; i < numChannels(); ++i) { - BufferPool::clear( m_fxChannels[i]->m_buffer, + MixHelpers::clear( m_fxChannels[i]->m_buffer, Engine::mixer()->framesPerPeriod() ); m_fxChannels[i]->reset(); m_fxChannels[i]->m_queued = false; diff --git a/src/core/MixHelpers.cpp b/src/core/MixHelpers.cpp index de1c5cfc3a8..7b5ca4851fa 100644 --- a/src/core/MixHelpers.cpp +++ b/src/core/MixHelpers.cpp @@ -86,6 +86,22 @@ void setNaNHandler( bool use ) s_NaNHandler = use; } +void clear(sampleFrame * src, int frames) +{ + for (sampleFrame* frame = src; frame < src + frames; frame++) { + (*frame)[0] = (*frame)[1] = 0.0; + } +} + +#ifndef LMMS_DISABLE_SURROUND +void clear(surroundSampleFrame *src, int frames) +{ + for (surroundSampleFrame* frame = src; frame < src + frames; frame++) { + (*frame)[0] = (*frame)[1] = 0.0; + } +} +#endif + /*! \brief Function for sanitizing a buffer of infs/nans - returns true if those are found */ bool sanitize( sampleFrame * src, int frames ) { diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index 1cf0635696e..19bfe77585a 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -37,6 +37,7 @@ #include "ConfigManager.h" #include "SamplePlayHandle.h" #include "Memory.h" +#include "MixHelpers.h" #include "BufferPool.h" // platform-specific audio-interface-classes @@ -97,7 +98,7 @@ Mixer::Mixer( bool renderOnly ) : m_inputBufferFrames[i] = 0; m_inputBufferSize[i] = DEFAULT_BUFFER_SIZE * 100; m_inputBuffer[i] = new sampleFrame[ DEFAULT_BUFFER_SIZE * 100 ]; - BufferPool::clear( m_inputBuffer[i], m_inputBufferSize[i] ); + MixHelpers::clear( m_inputBuffer[i], m_inputBufferSize[i] ); } // determine FIFO size and number of frames per period @@ -140,7 +141,7 @@ Mixer::Mixer( bool renderOnly ) : { m_readBuf = alloc.allocate( m_framesPerPeriod ); - BufferPool::clear( m_readBuf, m_framesPerPeriod ); + MixHelpers::clear( m_readBuf, m_framesPerPeriod ); m_bufferPool.push_back( m_readBuf ); } @@ -416,7 +417,7 @@ const surroundSampleFrame * Mixer::renderNextBuffer() m_readBuf = m_bufferPool[m_readBuffer]; // clear last audio-buffer - BufferPool::clear( m_writeBuf, m_framesPerPeriod ); + MixHelpers::clear( m_writeBuf, m_framesPerPeriod ); // prepare master mix (clear internal buffers etc.) FxMixer * fxMixer = Engine::fxMixer(); diff --git a/src/core/Oscillator.cpp b/src/core/Oscillator.cpp index bb06d98042c..1437c789c6a 100644 --- a/src/core/Oscillator.cpp +++ b/src/core/Oscillator.cpp @@ -24,8 +24,8 @@ #include "Oscillator.h" -#include "BufferPool.h" #include "Engine.h" +#include "MixHelpers.h" #include "Mixer.h" #include "AutomatableModel.h" @@ -59,7 +59,7 @@ void Oscillator::update( sampleFrame * _ab, const fpp_t _frames, { if( m_freq >= Engine::mixer()->processingSampleRate() / 2 ) { - BufferPool::clear( _ab, _frames ); + MixHelpers::clear( _ab, _frames ); return; } if( m_subOsc != NULL ) diff --git a/src/core/PlayHandle.cpp b/src/core/PlayHandle.cpp index 67ddb5e354f..04a1e5b73a2 100644 --- a/src/core/PlayHandle.cpp +++ b/src/core/PlayHandle.cpp @@ -22,10 +22,11 @@ * */ -#include "PlayHandle.h" #include "BufferPool.h" +#include "PlayHandle.h" #include "Engine.h" #include "Mixer.h" +#include "MixHelpers.h" #include #include @@ -54,7 +55,7 @@ void PlayHandle::doProcessing() if( m_usesBuffer ) { m_bufferReleased = false; - BufferPool::clear(m_playHandleBuffer, Engine::mixer()->framesPerPeriod()); + MixHelpers::clear(m_playHandleBuffer, Engine::mixer()->framesPerPeriod()); play( buffer() ); } else diff --git a/src/core/RemotePlugin.cpp b/src/core/RemotePlugin.cpp index 82bec26719e..4121177edb9 100644 --- a/src/core/RemotePlugin.cpp +++ b/src/core/RemotePlugin.cpp @@ -28,9 +28,9 @@ #include #endif -#include "BufferPool.h" #include "RemotePlugin.h" #include "Mixer.h" +#include "MixHelpers.h" #include "Engine.h" #include @@ -287,7 +287,7 @@ bool RemotePlugin::process( const sampleFrame * _in_buf, { if( _out_buf != NULL ) { - BufferPool::clear( _out_buf, frames ); + MixHelpers::clear( _out_buf, frames ); } return false; } @@ -306,7 +306,7 @@ bool RemotePlugin::process( const sampleFrame * _in_buf, } if( _out_buf != NULL ) { - BufferPool::clear( _out_buf, frames ); + MixHelpers::clear( _out_buf, frames ); } return false; } @@ -380,7 +380,7 @@ bool RemotePlugin::process( const sampleFrame * _in_buf, sampleFrame * o = (sampleFrame *) ( m_shm + m_inputCount*frames ); // clear buffer, if plugin didn't fill up both channels - BufferPool::clear( _out_buf, frames ); + MixHelpers::clear( _out_buf, frames ); for( ch_cnt_t ch = 0; ch < qMin( DEFAULT_CHANNELS, outputs ); ++ch ) diff --git a/src/core/audio/AudioPort.cpp b/src/core/audio/AudioPort.cpp index 91bd2d9d97d..90d95cc9fe8 100644 --- a/src/core/audio/AudioPort.cpp +++ b/src/core/audio/AudioPort.cpp @@ -111,7 +111,7 @@ void AudioPort::doProcessing() const fpp_t fpp = Engine::mixer()->framesPerPeriod(); // clear the buffer - BufferPool::clear( m_portBuffer, fpp ); + MixHelpers::clear( m_portBuffer, fpp ); //qDebug( "Playhandles: %d", m_playHandles.size() ); for( PlayHandle * ph : m_playHandles ) // now we mix all playhandle buffers into the audioport buffer diff --git a/src/gui/widgets/VisualizationWidget.cpp b/src/gui/widgets/VisualizationWidget.cpp index 2d933ec8072..0e8406755de 100644 --- a/src/gui/widgets/VisualizationWidget.cpp +++ b/src/gui/widgets/VisualizationWidget.cpp @@ -31,11 +31,11 @@ #include "gui_templates.h" #include "MainWindow.h" #include "Mixer.h" +#include "MixHelpers.h" #include "Engine.h" #include "ToolTip.h" #include "Song.h" -#include "BufferPool.h" VisualizationWidget::VisualizationWidget( const QPixmap & _bg, QWidget * _p, @@ -55,7 +55,7 @@ VisualizationWidget::VisualizationWidget( const QPixmap & _bg, QWidget * _p, const fpp_t frames = Engine::mixer()->framesPerPeriod(); m_buffer = new sampleFrame[frames]; - BufferPool::clear( m_buffer, frames ); + MixHelpers::clear( m_buffer, frames ); ToolTip::add( this, tr( "Oscilloscope" ) ); From bd1ee2983b53b2f58b5fb4c7b730f57bc0d10b28 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Sun, 25 Aug 2019 23:49:22 +0200 Subject: [PATCH 15/28] Silence int conversion warning --- src/core/NotePlayHandle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index c7102003484..b2a80a6255d 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -542,5 +542,5 @@ void NotePlayHandle::resize( const bpm_t _new_tempo ) } } -const int INITIAL_NPH_CACHE = 256; +const size_t INITIAL_NPH_CACHE = 256; MemoryPool NotePlayHandlePool{INITIAL_NPH_CACHE}; From e21c00e9b73014c9b09b2cfe649d87d2cb6217ba Mon Sep 17 00:00:00 2001 From: Lukas W Date: Mon, 4 May 2020 18:00:47 +0200 Subject: [PATCH 16/28] Apply suggestions by @PhysSong --- include/MemoryPool.h | 2 +- plugins/CMakeLists.txt | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/include/MemoryPool.h b/include/MemoryPool.h index 1166a5a6fa9..d8155013746 100644 --- a/include/MemoryPool.h +++ b/include/MemoryPool.h @@ -39,7 +39,7 @@ class MemoryPool : private _MemoryPool_Base using value_type = T; template struct rebind { typedef MemoryPool other; }; - MemoryPool(size_t nmemb) : _MemoryPool_Base(sizeof(T), nmemb) {} + MemoryPool(size_t nmemb) : _MemoryPool_Base(sizeof(T), nmemb) {} T * allocate(size_t n = 1) { diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index fe8a5faa927..4f139f8b32b 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -9,13 +9,6 @@ IF(LMMS_BUILD_APPLE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") ENDIF() -IF(MINGW_PREFIX) - # There's a bug in some CMake or MinGW versions that passes -std=c++11 when - # compiling C files (e.g. fmopl.c). Remove -Werror for plugins to work - # around this. - STRING(REPLACE "-Werror " "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) -ENDIF() - INCLUDE_DIRECTORIES( ${SAMPLERATE_INCLUDE_DIRS} "${CMAKE_BINARY_DIR}/src" From 62606b64fecf31e308922da41e18b51b6ec8caaa Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 6 May 2020 12:38:12 +0200 Subject: [PATCH 17/28] Try to fix CircleCI linux build --- CMakeLists.txt | 3 --- tests/CMakeLists.txt | 4 +++- tests/src/core/MemoryPoolTest.cpp | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 63807f0d158..d04318e514f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -171,9 +171,6 @@ ENDIF() # Resolve Qt5::qmake to full path for use in packaging scripts GET_TARGET_PROPERTY(QT_QMAKE_EXECUTABLE "${Qt5Core_QMAKE_EXECUTABLE}" IMPORTED_LOCATION) -FIND_PACKAGE(Qt5Test) -SET(QT_QTTEST_LIBRARY Qt5::Test) - # check for libsndfile FIND_PACKAGE(SndFile REQUIRED) IF(NOT SNDFILE_FOUND) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c7e3a6b53ff..ed77e25e8b9 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,6 +6,8 @@ INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}/src") SET(CMAKE_CXX_STANDARD 11) +FIND_PACKAGE(Qt5Test) + SET(CMAKE_AUTOMOC ON) ADD_EXECUTABLE(tests @@ -24,5 +26,5 @@ ADD_EXECUTABLE(tests TARGET_COMPILE_DEFINITIONS(tests PRIVATE $ ) -TARGET_LINK_LIBRARIES(tests ${QT_LIBRARIES} ${QT_QTTEST_LIBRARY}) +TARGET_LINK_LIBRARIES(tests ${QT_LIBRARIES} Qt5::Test) TARGET_LINK_LIBRARIES(tests ${LMMS_REQUIRED_LIBS}) diff --git a/tests/src/core/MemoryPoolTest.cpp b/tests/src/core/MemoryPoolTest.cpp index 2358cc40f21..0e946b184ee 100644 --- a/tests/src/core/MemoryPoolTest.cpp +++ b/tests/src/core/MemoryPoolTest.cpp @@ -44,7 +44,7 @@ private slots: ptrs.push(pool.allocate_bounded()); QVERIFY(ptrs.top()); } - QCOMPARE(pool.allocate_bounded(), nullptr); + QCOMPARE(pool.allocate_bounded(), static_cast(nullptr)); ptrs.push(pool.allocate()); QVERIFY(ptrs.top()); From 1cd8b7a895d77af313d8deec8765f234df8e6aed Mon Sep 17 00:00:00 2001 From: Lukas W Date: Mon, 11 May 2020 14:55:29 +0200 Subject: [PATCH 18/28] Fix libcds nifty counter typo Thanks @PhysSong Co-authored-by: Hyunjin Song --- include/libcds.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/libcds.h b/include/libcds.h index 7acbabea7da..7d4af908440 100644 --- a/include/libcds.h +++ b/include/libcds.h @@ -17,6 +17,5 @@ namespace _cdslib void thread_deinit(); static NiftyCounter _counter; - static NiftyCounterTL _thread_counter; + static NiftyCounterTL _thread_counter; } - From 29df8718005642b9da4192b3e3a00f9d97fc7af3 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 6 May 2020 15:08:48 +0200 Subject: [PATCH 19/28] Add nifty counter instance to MmAllocaator Prevents exit crashes in rare cases e.g. when Engine is not destroyed --- include/Memory.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/Memory.h b/include/Memory.h index 243d1e47657..5425b6c8704 100644 --- a/include/Memory.h +++ b/include/Memory.h @@ -75,6 +75,7 @@ class MmAllocator typedef std::vector > vector; private: + MemoryManager::MmCounter m_counter; MemoryManager::ThreadGuard m_threadGuard; }; From 78c92e83145b027d693792a79e1e25ab3f745f01 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Wed, 6 May 2020 15:09:51 +0200 Subject: [PATCH 20/28] Tests: Allow specifying test suit name --- tests/main.cpp | 47 +++++++++++++++++++++++++------ tests/src/core/MemoryPoolTest.cpp | 5 ++-- 2 files changed, 41 insertions(+), 11 deletions(-) diff --git a/tests/main.cpp b/tests/main.cpp index 2cf71aaa52d..42ad8e39fcf 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -6,20 +6,49 @@ #include "Engine.h" +void printAvailableSuits() +{ + QStringList suitNames; + for (QTestSuite* suite : QTestSuite::suites()) { + suitNames.push_back(suite->metaObject()->className()); + } + qDebug().noquote() << "Available test suits are: " << suitNames.join(", "); +} + +int runSuit(const QString& name, const QStringList& args) +{ + for (QTestSuite* suite : QTestSuite::suites()) { + if (suite->metaObject()->className() == name) { + return QTest::qExec(suite, args); + } + } + throw std::invalid_argument("No such test suit " + name.toStdString()); +} + int main(int argc, char* argv[]) { - new QCoreApplication(argc, argv); + auto app = new QCoreApplication(argc, argv); Engine::init(true); - int numsuites = QTestSuite::suites().size(); - qDebug() << ">> Will run" << numsuites << "test suites"; - int failed = 0; - for (QTestSuite*& suite : QTestSuite::suites()) - { - failed += QTest::qExec(suite, argc, argv); + int rc = 0; + + if (app->arguments().size() > 1) { + try { + runSuit(app->arguments()[1], app->arguments().mid(1)); + } catch (const std::invalid_argument& e) { + qDebug().noquote() << e.what(); + printAvailableSuits(); + rc = -1; + } + } else { + int numsuites = QTestSuite::suites().size(); + qDebug() << ">> Will run" << numsuites << "test suites"; + for (QTestSuite* suite : QTestSuite::suites()) { + rc += QTest::qExec(suite, argc, argv); + } + qDebug() << "<<" << rc << "out of"<; - MemoryPool pool(256); + int n = 256; + MemoryPool pool(n); std::stack ptrs; - for (int i=0; i < 256; i++) { + for (int i=0; i < n; i++) { ptrs.push(pool.allocate_bounded()); QVERIFY(ptrs.top()); } From 5ae42cafc405c88f9d3b15b6145b964a8ef093ab Mon Sep 17 00:00:00 2001 From: Lukas W Date: Mon, 11 May 2020 17:11:11 +0200 Subject: [PATCH 21/28] Try to fix libcds counters issues * For unknown reasons, _cdslib::_thread_counter is never initialized, trigger initialization manually by referencing during MemoryPool's construction. * CircleCI linux.gcc test crashes on exit with an "invalid delete" at hpGC.reset() in libcds.cpp. I don't know what causes this, but it turns out we don't need garbage collection currently (we only use VyukovMPMCCycleQueue), so we can just remove the garbage collection for now. --- include/libcds.h | 4 +++- src/core/MemoryPool.cpp | 2 ++ src/core/libcds.cpp | 13 ++++++------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/include/libcds.h b/include/libcds.h index 7d4af908440..ac051ca00a1 100644 --- a/include/libcds.h +++ b/include/libcds.h @@ -17,5 +17,7 @@ namespace _cdslib void thread_deinit(); static NiftyCounter _counter; - static NiftyCounterTL _thread_counter; + static thread_local NiftyCounterTL<_cdslib::thread_init, _cdslib::thread_deinit> _thread_counter; } + +#define CDS_THREAD_GUARD() (void)_cdslib::_thread_counter; diff --git a/src/core/MemoryPool.cpp b/src/core/MemoryPool.cpp index 62dfad078c2..fce0c14df77 100644 --- a/src/core/MemoryPool.cpp +++ b/src/core/MemoryPool.cpp @@ -28,6 +28,8 @@ class _MemoryPool_Private : MmAllocator , m_numElms(nmemb) , m_freelist(nmemb) { + CDS_THREAD_GUARD(); + m_buffer = new char[m_elementSize * m_numElms]; for (size_t i = 0; i < m_numElms; i++) { m_freelist.push(m_buffer + (i * m_elementSize)); diff --git a/src/core/libcds.cpp b/src/core/libcds.cpp index ef7ac3a88bb..eb97a161665 100644 --- a/src/core/libcds.cpp +++ b/src/core/libcds.cpp @@ -1,7 +1,6 @@ #include "libcds.h" #include -#include #include #include "stdshims.h" @@ -9,28 +8,28 @@ namespace _cdslib { -static std::unique_ptr hpGC; - void init() { cds::Initialize(); - hpGC = make_unique(); } void deinit() { - hpGC.reset(); cds::Terminate(); } void thread_init() { - cds::threading::Manager::attachThread(); + if (! cds::threading::Manager::isThreadAttached()) { + cds::threading::Manager::attachThread(); + } } void thread_deinit() { - cds::threading::Manager::detachThread(); + if (cds::threading::Manager::isThreadAttached()) { + cds::threading::Manager::detachThread(); + } } } From a64f83e0ed3db685de33c5340d124cda3415c2b7 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Mon, 11 May 2020 15:20:36 +0200 Subject: [PATCH 22/28] Fix libcds MSVC compilation * Update to include 4227281c367a0dd36765bba58bd9bb6f43ceb88b fixing https://github.com/khizmax/libcds/issues/124 * Make CDS_BUILD_STATIC_LIB compile definition public to avoid dllimport attribute in defs.h * Make dependencies' defintions actually propagate to lmmsobjs --- src/3rdparty/CMakeLists.txt | 2 +- src/3rdparty/libcds | 2 +- src/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index 16fea6b6305..01cf80dee0a 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -52,7 +52,7 @@ ENDIF() IF(CDS_LIBRARY_TYPE STREQUAL "STATIC") TARGET_COMPILE_DEFINITIONS(cds - PRIVATE CDS_BUILD_STATIC_LIB + PUBLIC CDS_BUILD_STATIC_LIB ) ELSE() TARGET_COMPILE_DEFINITIONS(cds diff --git a/src/3rdparty/libcds b/src/3rdparty/libcds index e5bba766b93..44c052bdb69 160000 --- a/src/3rdparty/libcds +++ b/src/3rdparty/libcds @@ -1 +1 @@ -Subproject commit e5bba766b939f96b5f47fe470a3711ff3afe9ee2 +Subproject commit 44c052bdb69aaf26d7010074547356c80e55421a diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 79241ab51f5..8dce3de7c19 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -123,7 +123,7 @@ TARGET_INCLUDE_DIRECTORIES(lmms # See the documentation of DEFINE_SYMBOL for details. # Also add LMMS_STATIC_DEFINE for targets linking against it. TARGET_COMPILE_DEFINITIONS(lmmsobjs - PRIVATE -Dlmmsobjs_EXPORTS + PRIVATE -Dlmmsobjs_EXPORTS $ INTERFACE -DLMMS_STATIC_DEFINE ) TARGET_COMPILE_DEFINITIONS(lmms From ac0081de10dc1c494c8366b93cc3e0cc9e275a03 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Thu, 14 May 2020 10:06:14 +0200 Subject: [PATCH 23/28] Fix crash on exit with MSVC --- include/Memory.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/include/Memory.h b/include/Memory.h index 5425b6c8704..91a5a54e73d 100644 --- a/include/Memory.h +++ b/include/Memory.h @@ -51,6 +51,7 @@ class LMMS_EXPORT MemoryManager }; static MemoryManager::MmCounter _mm_counter; +static thread_local MemoryManager::MmCounter _mm_thread_counter; template class MmAllocator @@ -73,10 +74,6 @@ class MmAllocator } typedef std::vector > vector; - -private: - MemoryManager::MmCounter m_counter; - MemoryManager::ThreadGuard m_threadGuard; }; class _AlignedAllocator_Base From 846ca178f558ff8cd9cfbb188b82b047ac1504e7 Mon Sep 17 00:00:00 2001 From: Lukas W Date: Fri, 22 May 2020 17:20:08 +0200 Subject: [PATCH 24/28] CMake: Build lmms shared library instead of object library Resolves some inexplicable linking errors on Windows. Saves us from working around incomplete CMake support of object libraries. --- CMakeLists.txt | 2 +- benchmarks/CMakeLists.txt | 3 +- cmake/linux/package_linux.sh.in | 2 +- cmake/modules/BuildPlugin.cmake | 2 +- include/AutomationTrack.h | 2 +- include/BBTrack.h | 3 +- include/MainApplication.h | 3 +- include/MainWindow.h | 6 +- include/Memory.h | 2 +- include/MemoryPool.h | 5 +- include/MixHelpers.h | 3 +- include/MixerProfiler.h | 3 +- include/ModelVisitor.h | 6 +- include/ProjectVersion.h | 3 +- include/RenderManager.h | 2 +- plugins/LadspaEffect/calf/CMakeLists.txt | 2 +- src/3rdparty/rpmalloc/CMakeLists.txt | 5 +- src/CMakeLists.txt | 142 ++++++++--------------- tests/CMakeLists.txt | 7 +- 19 files changed, 80 insertions(+), 123 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9fe8202eac..815d591bc6a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -388,7 +388,7 @@ IF(WANT_JACK) IF(JACK_FOUND) IF(WANT_WEAKJACK) SET(LMMS_HAVE_WEAKJACK TRUE) - SET(WEAKJACK_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/src/3rdparty/weakjack/weakjack) + SET(WEAKJACK_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/src/3rdparty/weakjack/weakjack") SET(STATUS_JACK "OK (weak linking enabled)") # use dlsym instead SET(JACK_LIBRARIES ${CMAKE_DL_LIBS}) diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt index 49cc4ee2f06..934903d933c 100644 --- a/benchmarks/CMakeLists.txt +++ b/benchmarks/CMakeLists.txt @@ -10,6 +10,5 @@ SET(CMAKE_AUTOMOC ON) ADD_EXECUTABLE(benchmarks EXCLUDE_FROM_ALL benchmark.cpp - $ ) -TARGET_LINK_LIBRARIES(benchmarks ${QT_LIBRARIES} ${LMMS_REQUIRED_LIBS}) +TARGET_LINK_LIBRARIES(benchmarks lmmslib) diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index a1f9ff8658f..d32cbb067f3 100644 --- a/cmake/linux/package_linux.sh.in +++ b/cmake/linux/package_linux.sh.in @@ -108,7 +108,7 @@ chmod +x "${APPDIR}usr/bin/lmms" unset LD_LIBRARY_PATH # Ensure linuxdeployqt can find shared objects -export LD_LIBRARY_PATH="${APPDIR}"usr/lib/lmms/:"${APPDIR}"usr/lib/lmms/optional:"$LD_LIBRARY_PATH" +export LD_LIBRARY_PATH="${APPDIR}"usr/lib/:"${APPDIR}"usr/lib/lmms/:"${APPDIR}"usr/lib/lmms/optional:"$LD_LIBRARY_PATH" # Move executables so linuxdeployqt can find them ZYNLIB="${APPDIR}usr/lib/lmms/RemoteZynAddSubFx" diff --git a/cmake/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake index 8b9c9f4d0cf..d86fbd057b3 100644 --- a/cmake/modules/BuildPlugin.cmake +++ b/cmake/modules/BuildPlugin.cmake @@ -60,7 +60,7 @@ FUNCTION(BUILD_PLUGIN PLUGIN_NAME) ADD_LIBRARY(${PLUGIN_NAME} ${PLUGIN_LINK} ${PLUGIN_SOURCES} ${plugin_MOC_out} ${RCC_OUT}) - TARGET_LINK_LIBRARIES(${PLUGIN_NAME} Qt5::Widgets Qt5::Xml lmms) + TARGET_LINK_LIBRARIES(${PLUGIN_NAME} Qt5::Widgets Qt5::Xml lmmslib) INSTALL(TARGETS ${PLUGIN_NAME} LIBRARY DESTINATION "${PLUGIN_DESTINATION}" diff --git a/include/AutomationTrack.h b/include/AutomationTrack.h index 92a50dd04a9..cdf1086678e 100644 --- a/include/AutomationTrack.h +++ b/include/AutomationTrack.h @@ -30,7 +30,7 @@ #include "Track.h" -class AutomationTrack : public Track +class LMMS_EXPORT AutomationTrack : public Track { Q_OBJECT public: diff --git a/include/BBTrack.h b/include/BBTrack.h index 70195f28de6..02d9d669283 100644 --- a/include/BBTrack.h +++ b/include/BBTrack.h @@ -31,13 +31,14 @@ #include #include +#include "lmms_export.h" #include "Track.h" class TrackLabelButton; class TrackContainer; -class BBTCO : public TrackContentObject +class LMMS_EXPORT BBTCO : public TrackContentObject { public: BBTCO( Track * _track ); diff --git a/include/MainApplication.h b/include/MainApplication.h index d28900213c9..bafa9baeb1e 100644 --- a/include/MainApplication.h +++ b/include/MainApplication.h @@ -25,6 +25,7 @@ #ifndef MAINAPPLICATION_H #define MAINAPPLICATION_H +#include "lmms_export.h" #include "lmmsconfig.h" #include @@ -35,7 +36,7 @@ #endif #if defined(LMMS_BUILD_WIN32) -class MainApplication : public QApplication, public QAbstractNativeEventFilter +class LMMS_EXPORT MainApplication : public QApplication, public QAbstractNativeEventFilter #else class MainApplication : public QApplication #endif diff --git a/include/MainWindow.h b/include/MainWindow.h index c894ef4f0e4..f7325395928 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -25,6 +25,8 @@ #ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H +#include "lmms_export.h" + #include #include #include @@ -43,7 +45,7 @@ class PluginView; class ToolButton; -class MainWindow : public QMainWindow +class LMMS_EXPORT MainWindow : public QMainWindow { Q_OBJECT public: @@ -61,7 +63,7 @@ class MainWindow : public QMainWindow void addSpacingToToolBar( int _size ); // wrap the widget with a window decoration and add it to the workspace - LMMS_EXPORT SubWindow* addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags=0); + SubWindow* addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags=0); /// diff --git a/include/Memory.h b/include/Memory.h index 91a5a54e73d..5769e662329 100644 --- a/include/Memory.h +++ b/include/Memory.h @@ -54,7 +54,7 @@ static MemoryManager::MmCounter _mm_counter; static thread_local MemoryManager::MmCounter _mm_thread_counter; template -class MmAllocator +class LMMS_EXPORT MmAllocator { public: MmAllocator() = default; diff --git a/include/MemoryPool.h b/include/MemoryPool.h index d8155013746..12086196807 100644 --- a/include/MemoryPool.h +++ b/include/MemoryPool.h @@ -14,10 +14,11 @@ #include #include +#include "lmms_export.h" -class _MemoryPool_Private; +class LMMS_EXPORT _MemoryPool_Private; -class _MemoryPool_Base +class LMMS_EXPORT _MemoryPool_Base { public: _MemoryPool_Base(size_t size, size_t nmemb); diff --git a/include/MixHelpers.h b/include/MixHelpers.h index 2bef776c561..bd22c5ec9a5 100644 --- a/include/MixHelpers.h +++ b/include/MixHelpers.h @@ -26,6 +26,7 @@ #define MIX_HELPERS_H #include "lmms_basics.h" +#include "lmms_export.h" class ValueBuffer; namespace MixHelpers @@ -35,7 +36,7 @@ bool isSilent( const sampleFrame* src, int frames ); bool useNaNHandler(); -void setNaNHandler( bool use ); +LMMS_EXPORT void setNaNHandler( bool use ); void clear(sampleFrame * src, int frames); #ifndef LMMS_DISABLE_SURROUND diff --git a/include/MixerProfiler.h b/include/MixerProfiler.h index 0c46c34cb0d..26b842dde68 100644 --- a/include/MixerProfiler.h +++ b/include/MixerProfiler.h @@ -27,10 +27,11 @@ #include +#include "lmms_export.h" #include "lmms_basics.h" #include "MicroTimer.h" -class MixerProfiler +class LMMS_EXPORT MixerProfiler { public: MixerProfiler(); diff --git a/include/ModelVisitor.h b/include/ModelVisitor.h index f9d156e30f4..5161718b446 100644 --- a/include/ModelVisitor.h +++ b/include/ModelVisitor.h @@ -25,6 +25,8 @@ #ifndef MODELVISITOR_H #define MODELVISITOR_H +#include "lmms_export.h" + class AutomatableModel; class BoolModel; class IntModel; @@ -32,7 +34,7 @@ class FloatModel; class ComboBoxModel; class TempoSyncKnobModel; -class ModelVisitor +class LMMS_EXPORT ModelVisitor { template void up(ModelType& m) { visit(static_cast(m)); } @@ -46,7 +48,7 @@ class ModelVisitor virtual ~ModelVisitor(); }; -class ConstModelVisitor +class LMMS_EXPORT ConstModelVisitor { template void up(const ModelType& m) { diff --git a/include/ProjectVersion.h b/include/ProjectVersion.h index 5f7bf09b3c1..439bdffbdff 100644 --- a/include/ProjectVersion.h +++ b/include/ProjectVersion.h @@ -28,12 +28,13 @@ #define PROJECT_VERSION_H #include +#include "lmms_export.h" /*! \brief Version number parsing and comparison * * Parses and compares version information. i.e. "1.0.3" < "1.0.10" */ -class ProjectVersion +class LMMS_EXPORT ProjectVersion { public: enum CompareType { Major, Minor, Release, Stage, Build }; diff --git a/include/RenderManager.h b/include/RenderManager.h index 01236d7476a..cd4879fece7 100644 --- a/include/RenderManager.h +++ b/include/RenderManager.h @@ -32,7 +32,7 @@ #include "OutputSettings.h" -class RenderManager : public QObject +class LMMS_EXPORT RenderManager : public QObject { Q_OBJECT public: diff --git a/plugins/LadspaEffect/calf/CMakeLists.txt b/plugins/LadspaEffect/calf/CMakeLists.txt index 58a40d99fbc..3e213c92cc6 100644 --- a/plugins/LadspaEffect/calf/CMakeLists.txt +++ b/plugins/LadspaEffect/calf/CMakeLists.txt @@ -50,4 +50,4 @@ IF(NOT LMMS_BUILD_APPLE AND NOT LMMS_BUILD_OPENBSD) SET_TARGET_PROPERTIES(veal PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined") ENDIF() -TARGET_LINK_LIBRARIES(veal lmms) +TARGET_LINK_LIBRARIES(veal lmmslib) diff --git a/src/3rdparty/rpmalloc/CMakeLists.txt b/src/3rdparty/rpmalloc/CMakeLists.txt index 3b3afa6d329..80d2302b0bc 100644 --- a/src/3rdparty/rpmalloc/CMakeLists.txt +++ b/src/3rdparty/rpmalloc/CMakeLists.txt @@ -7,7 +7,10 @@ target_include_directories(rpmalloc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/rpmalloc/rpmalloc ) -set_property(TARGET rpmalloc PROPERTY C_STANDARD 11) +set_target_properties(rpmalloc PROPERTIES + C_STANDARD 11 + POSITION_INDEPENDENT_CODE ON +) IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") target_compile_options(rpmalloc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8dce3de7c19..907647477fa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,14 +21,6 @@ ADD_SUBDIRECTORY(gui) ADD_SUBDIRECTORY(tracks) QT5_WRAP_UI(LMMS_UI_OUT ${LMMS_UIS}) -INCLUDE_DIRECTORIES( - "${CMAKE_CURRENT_BINARY_DIR}" - "${CMAKE_BINARY_DIR}" - "${CMAKE_BINARY_DIR}/include" - "${CMAKE_SOURCE_DIR}" - "${CMAKE_SOURCE_DIR}/include" - "${RINGBUFFER_DIR}/include" -) IF(WIN32 AND MSVC) SET(WINRC "${CMAKE_BINARY_DIR}/lmms.rc") @@ -49,49 +41,6 @@ ADD_GEN_QRC(LMMS_RCC_OUT lmms.qrc "${CONTRIBUTORS}" ) -# Paths relative to lmms executable -FILE(RELATIVE_PATH LIB_DIR_RELATIVE "/${BIN_DIR}" "/${LIB_DIR}") -FILE(RELATIVE_PATH PLUGIN_DIR_RELATIVE "/${BIN_DIR}" "/${PLUGIN_DIR}") -ADD_DEFINITIONS(-DLIB_DIR="${LIB_DIR_RELATIVE}" -DPLUGIN_DIR="${PLUGIN_DIR_RELATIVE}" ${PULSEAUDIO_DEFINITIONS} ${PORTAUDIO_DEFINITIONS}) -INCLUDE_DIRECTORIES( - ${JACK_INCLUDE_DIRS} - ${SAMPLERATE_INCLUDE_DIRS} - ${SNDFILE_INCLUDE_DIRS} - ${SNDIO_INCLUDE_DIRS} - ${FFTW3F_INCLUDE_DIRS} -) - -IF(NOT ("${SDL2_INCLUDE_DIR}" STREQUAL "")) - INCLUDE_DIRECTORIES("${SDL2_INCLUDE_DIR}") -ELSEIF(NOT ("${SDL_INCLUDE_DIR}" STREQUAL "")) - INCLUDE_DIRECTORIES("${SDL_INCLUDE_DIR}") -ENDIF() - -IF(LMMS_HAVE_WEAKJACK) - LIST(APPEND LMMS_SRCS "${WEAKJACK_INCLUDE_DIRS}/weak_libjack.c") - LIST(APPEND LMMS_INCLUDES "${WEAKJACK_INCLUDE_DIRS}/weak_libjack.h") - INCLUDE_DIRECTORIES("${WEAKJACK_INCLUDE_DIRS}") - ADD_DEFINITIONS(-DUSE_WEAK_JACK=1 -DNO_JACK_METADATA=1) -ENDIF() - -IF(NOT ("${PORTAUDIO_INCLUDE_DIR}" STREQUAL "")) - INCLUDE_DIRECTORIES("${PORTAUDIO_INCLUDE_DIR}") -ENDIF() - -IF(NOT ("${PULSEAUDIO_INCLUDE_DIR}" STREQUAL "")) - INCLUDE_DIRECTORIES("${PULSEAUDIO_INCLUDE_DIR}") -ENDIF() - -IF(NOT ("${OGGVORBIS_INCLUDE_DIR}" STREQUAL "")) - INCLUDE_DIRECTORIES("${OGGVORBIS_INCLUDE_DIR}") -ENDIF() - -IF(NOT ("${LAME_INCLUDE_DIRS}" STREQUAL "")) - INCLUDE_DIRECTORIES("${LAME_INCLUDE_DIRS}") -ENDIF() - -LIST(APPEND LMMS_SRCS "${RINGBUFFER_DIR}/src/lib/ringbuffer.cpp") - # Use libraries in non-standard directories (e.g., another version of Qt) IF(LMMS_BUILD_LINUX) LINK_LIBRARIES(-Wl,--enable-new-dtags) @@ -99,35 +48,60 @@ IF(LMMS_BUILD_LINUX) ENDIF() SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -ADD_LIBRARY(lmmsobjs OBJECT +ADD_LIBRARY(lmmslib SHARED ${LMMS_SRCS} ${LMMS_INCLUDES} ${LMMS_UI_OUT} ${LMMS_RCC_OUT} + ${RINGBUFFER_DIR}/src/lib/ringbuffer.cpp + $<$: + ${WEAKJACK_INCLUDE_DIR}/weak_libjack.c + ${WEAKJACK_INCLUDE_DIR}/weak_libjack.h + > ) -GENERATE_EXPORT_HEADER(lmmsobjs +GENERATE_EXPORT_HEADER(lmmslib BASE_NAME lmms ) ADD_EXECUTABLE(lmms core/main.cpp - $ "${WINRC}" ) -TARGET_INCLUDE_DIRECTORIES(lmms - PUBLIC ${CMAKE_CURRENT_BINARY_DIR} -) -# CMake doesn't define target_EXPORTS for OBJECT libraries. -# See the documentation of DEFINE_SYMBOL for details. -# Also add LMMS_STATIC_DEFINE for targets linking against it. -TARGET_COMPILE_DEFINITIONS(lmmsobjs - PRIVATE -Dlmmsobjs_EXPORTS $ - INTERFACE -DLMMS_STATIC_DEFINE +TARGET_INCLUDE_DIRECTORIES(lmmslib PUBLIC + "${CMAKE_CURRENT_BINARY_DIR}" + "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/include" + "${CMAKE_SOURCE_DIR}" + "${CMAKE_SOURCE_DIR}/include" + "${RINGBUFFER_DIR}/include" + ${JACK_INCLUDE_DIRS} + ${SAMPLERATE_INCLUDE_DIRS} + ${SNDFILE_INCLUDE_DIRS} + ${SNDIO_INCLUDE_DIRS} + ${FFTW3F_INCLUDE_DIRS} + ${SDL2_INCLUDE_DIR} + ${SDL_INCLUDE_DIR} + ${PORTAUDIO_INCLUDE_DIR} + ${PULSEAUDIO_INCLUDE_DIR} + ${OGGVORBIS_INCLUDE_DIR} + ${LAME_INCLUDE_DIRS} + ${WEAKJACK_INCLUDE_DIR} ) -TARGET_COMPILE_DEFINITIONS(lmms - PRIVATE $ + + +# Paths relative to lmms executable +FILE(RELATIVE_PATH LIB_DIR_RELATIVE "/${BIN_DIR}" "/${LIB_DIR}") +FILE(RELATIVE_PATH PLUGIN_DIR_RELATIVE "/${BIN_DIR}" "/${PLUGIN_DIR}") +TARGET_COMPILE_DEFINITIONS(lmmslib + PRIVATE + LIB_DIR="${LIB_DIR_RELATIVE}" + PLUGIN_DIR="${PLUGIN_DIR_RELATIVE}" + PUBLIC + ${PULSEAUDIO_DEFINITIONS} + ${PORTAUDIO_DEFINITIONS} + $<$:USE_WEAK_JACK=1 NO_JACK_METADATA=1> ) # Set Visual Studio startup project to lmms @@ -154,7 +128,7 @@ IF(LMMS_BUILD_HAIKU) SET(EXTRA_LIBRARIES "-lnetwork") ENDIF() -SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} +TARGET_LINK_LIBRARIES(lmmslib ${CMAKE_THREAD_LIBS_INIT} ${QT_LIBRARIES} ${ASOUND_LIBRARY} @@ -173,36 +147,9 @@ SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} rpmalloc cds ) +TARGET_LINK_LIBRARIES(lmms lmmslib) -# Expose required libs for tests binary -SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} PARENT_SCOPE) - -TARGET_LINK_LIBRARIES(lmms - ${LMMS_REQUIRED_LIBS} -) - -FOREACH(LIB ${LMMS_REQUIRED_LIBS}) - IF(TARGET ${LIB}) - GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES) - IF(INCLUDE_DIRS) - TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS}) - ENDIF() - ENDIF() -ENDFOREACH() - -SET_TARGET_PROPERTIES(lmms PROPERTIES - ENABLE_EXPORTS ON -) - -IF(LMMS_BUILD_WIN32) - IF(LMMS_BUILD_MSYS) - # ENABLE_EXPORTS property has no effect in some MSYS2 configurations. - # Add the linker flag manually to create liblmms.dll.a import library - SET_PROPERTY(TARGET lmms - APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--out-implib,liblmms.dll.a" - ) - ENDIF() -ELSE() +IF(NOT LMMS_BUILD_WIN32) if(CMAKE_INSTALL_MANDIR) SET(INSTALL_MANDIR ${CMAKE_INSTALL_MANDIR}) ELSE(CMAKE_INSTALL_MANDIR) @@ -213,4 +160,7 @@ ELSE() PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) ENDIF() -INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") +INSTALL(TARGETS lmms lmmslib + RUNTIME DESTINATION "${BIN_DIR}" + LIBRARY DESTINATION "${LIB_DIR}" +) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index ed77e25e8b9..b3830d8fc61 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -14,7 +14,6 @@ ADD_EXECUTABLE(tests EXCLUDE_FROM_ALL main.cpp QTestSuite - $ src/core/AutomatableModelTest.cpp src/core/ProjectVersionTest.cpp @@ -23,8 +22,4 @@ ADD_EXECUTABLE(tests src/tracks/AutomationTrackTest.cpp ) -TARGET_COMPILE_DEFINITIONS(tests - PRIVATE $ -) -TARGET_LINK_LIBRARIES(tests ${QT_LIBRARIES} Qt5::Test) -TARGET_LINK_LIBRARIES(tests ${LMMS_REQUIRED_LIBS}) +TARGET_LINK_LIBRARIES(tests lmmslib Qt5::Test) From ac5b3f07d798a0b3763e107ed67a0bceb78697b0 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Sat, 21 Sep 2024 21:48:04 +0900 Subject: [PATCH 25/28] Revert irrelevant changes --- CMakeLists.txt | 7 +- cmake/linux/package_linux.sh.in | 2 +- cmake/modules/BuildPlugin.cmake | 34 ++-- cmake/modules/DetectMachine.cmake | 26 --- .../toolchains/common/Ubuntu-MinGW-W64.cmake | 5 +- include/AudioPort.h | 2 +- include/AutomatableModel.h | 2 +- include/AutomationTrack.h | 2 +- include/BBTrack.h | 3 +- include/BasicFilters.h | 2 +- include/DataFile.h | 2 +- include/Delay.h | 2 +- include/DetuningHelper.h | 2 +- include/Effect.h | 2 +- include/Instrument.h | 2 +- include/MainApplication.h | 3 +- include/MainWindow.h | 6 +- include/MemoryHelper.h | 42 +++++ include/{Memory.h => MemoryManager.h} | 62 ++----- include/MidiEventProcessor.h | 2 +- include/MixerProfiler.h | 3 +- include/ModelVisitor.h | 6 +- include/PlayHandle.h | 2 +- include/Plugin.h | 2 +- include/ProjectVersion.h | 3 +- include/RenderManager.h | 2 +- include/RingBuffer.h | 2 +- include/SampleBuffer.h | 2 +- include/ValueBuffer.h | 2 +- plugins/FreeBoy/Gb_Apu_Buffer.h | 2 +- plugins/GigPlayer/GigPlayer.h | 2 +- plugins/LadspaEffect/LadspaEffect.cpp | 2 +- plugins/LadspaEffect/calf/CMakeLists.txt | 2 - plugins/Xpressive/ExprSynth.h | 2 +- plugins/bit_invader/bit_invader.h | 2 +- plugins/kicker/CMakeLists.txt | 2 +- plugins/kicker/KickerOsc.h | 2 +- plugins/nes/Nes.h | 2 +- plugins/patman/patman.h | 2 +- plugins/sf2_player/sf2_player.h | 2 +- plugins/sfxr/sfxr.h | 2 +- plugins/vestige/vestige.cpp | 1 + plugins/vibed/string_container.h | 2 +- plugins/watsyn/Watsyn.h | 2 +- src/3rdparty/rpmalloc/CMakeLists.txt | 5 +- src/CMakeLists.txt | 159 ++++++++++++------ src/core/CMakeLists.txt | 3 +- src/core/InstrumentFunctions.cpp | 1 + src/core/MemoryHelper.cpp | 65 +++++++ src/core/{Memory.cpp => MemoryManager.cpp} | 67 ++++---- src/core/MemoryPool.cpp | 2 +- src/core/Mixer.cpp | 13 +- src/core/NotePlayHandle.cpp | 1 + tests/CMakeLists.txt | 9 +- 54 files changed, 341 insertions(+), 247 deletions(-) create mode 100644 include/MemoryHelper.h rename include/{Memory.h => MemoryManager.h} (60%) create mode 100644 src/core/MemoryHelper.cpp rename src/core/{Memory.cpp => MemoryManager.cpp} (67%) diff --git a/CMakeLists.txt b/CMakeLists.txt index eca2b5b5643..7920f69d3f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,8 +160,6 @@ INCLUDE_DIRECTORIES( ${Qt5Xml_INCLUDE_DIRS} ) -INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/src/3rdparty/mingw-std-threads") - SET(QT_LIBRARIES Qt5::Core Qt5::Gui @@ -188,6 +186,9 @@ IF(EXISTS "${QT_TRANSLATIONS_DIR}") ADD_DEFINITIONS(-D'QT_TRANSLATIONS_DIR="${QT_TRANSLATIONS_DIR}"') ENDIF() +FIND_PACKAGE(Qt5Test) +SET(QT_QTTEST_LIBRARY Qt5::Test) + # check for libsndfile FIND_PACKAGE(SndFile REQUIRED) IF(NOT SNDFILE_FOUND) @@ -441,7 +442,7 @@ ENDIF(NOT LMMS_HAVE_ALSA) IF(WANT_JACK) IF(WANT_WEAKJACK) SET(LMMS_HAVE_WEAKJACK TRUE) - SET(WEAKJACK_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/3rdparty/weakjack/weakjack) + SET(WEAKJACK_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/src/3rdparty/weakjack/weakjack) SET(JACK_INCLUDE_DIRS ${CMAKE_SOURCE_DIR}/src/3rdparty/jack2/common) SET(STATUS_JACK "OK (weak linking enabled)") # use dlsym instead diff --git a/cmake/linux/package_linux.sh.in b/cmake/linux/package_linux.sh.in index d32cbb067f3..a1f9ff8658f 100644 --- a/cmake/linux/package_linux.sh.in +++ b/cmake/linux/package_linux.sh.in @@ -108,7 +108,7 @@ chmod +x "${APPDIR}usr/bin/lmms" unset LD_LIBRARY_PATH # Ensure linuxdeployqt can find shared objects -export LD_LIBRARY_PATH="${APPDIR}"usr/lib/:"${APPDIR}"usr/lib/lmms/:"${APPDIR}"usr/lib/lmms/optional:"$LD_LIBRARY_PATH" +export LD_LIBRARY_PATH="${APPDIR}"usr/lib/lmms/:"${APPDIR}"usr/lib/lmms/optional:"$LD_LIBRARY_PATH" # Move executables so linuxdeployqt can find them ZYNLIB="${APPDIR}usr/lib/lmms/RemoteZynAddSubFx" diff --git a/cmake/modules/BuildPlugin.cmake b/cmake/modules/BuildPlugin.cmake index d86fbd057b3..675433e631b 100644 --- a/cmake/modules/BuildPlugin.cmake +++ b/cmake/modules/BuildPlugin.cmake @@ -5,14 +5,10 @@ INCLUDE(GenQrc) -FUNCTION(BUILD_PLUGIN PLUGIN_NAME) - CMAKE_PARSE_ARGUMENTS(PLUGIN "" "DESTINATION;LINK;EXPORT_BASE_NAME" "MOCFILES;EMBEDDED_RESOURCES;UICFILES" ${ARGN}) +MACRO(BUILD_PLUGIN PLUGIN_NAME) + CMAKE_PARSE_ARGUMENTS(PLUGIN "" "LINK;EXPORT_BASE_NAME" "MOCFILES;EMBEDDED_RESOURCES;UICFILES" ${ARGN}) SET(PLUGIN_SOURCES ${PLUGIN_UNPARSED_ARGUMENTS}) - IF(NOT PLUGIN_DESTINATION) - SET(PLUGIN_DESTINATION "${PLUGIN_DIR}") - ENDIF() - INCLUDE_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_BINARY_DIR}" "${CMAKE_SOURCE_DIR}/include") ADD_DEFINITIONS(-DPLUGIN_NAME=${PLUGIN_NAME}) @@ -60,17 +56,26 @@ FUNCTION(BUILD_PLUGIN PLUGIN_NAME) ADD_LIBRARY(${PLUGIN_NAME} ${PLUGIN_LINK} ${PLUGIN_SOURCES} ${plugin_MOC_out} ${RCC_OUT}) - TARGET_LINK_LIBRARIES(${PLUGIN_NAME} Qt5::Widgets Qt5::Xml lmmslib) + TARGET_LINK_LIBRARIES(${PLUGIN_NAME} Qt5::Widgets Qt5::Xml) + + IF(LMMS_BUILD_WIN32) + TARGET_LINK_LIBRARIES(${PLUGIN_NAME} lmms) + ENDIF(LMMS_BUILD_WIN32) INSTALL(TARGETS ${PLUGIN_NAME} - LIBRARY DESTINATION "${PLUGIN_DESTINATION}" - RUNTIME DESTINATION "${PLUGIN_DESTINATION}" + LIBRARY DESTINATION "${PLUGIN_DIR}" + RUNTIME DESTINATION "${PLUGIN_DIR}" ) - IF(LMMS_BUILD_APPLE AND "${PLUGIN_LINK}" STREQUAL "SHARED") - SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") - ENDIF() - IF(LMMS_BUILD_WIN32 AND STRIP) + IF(LMMS_BUILD_APPLE) + IF ("${PLUGIN_LINK}" STREQUAL "SHARED") + SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup") + ELSE() + SET_TARGET_PROPERTIES(${PLUGIN_NAME} PROPERTIES LINK_FLAGS "-bundle_loader \"${CMAKE_BINARY_DIR}/lmms\"") + ENDIF() + ADD_DEPENDENCIES(${PLUGIN_NAME} lmms) + ENDIF(LMMS_BUILD_APPLE) + IF(LMMS_BUILD_WIN32) IF(STRIP) ADD_CUSTOM_COMMAND(TARGET ${PLUGIN_NAME} POST_BUILD COMMAND ${STRIP} "$") ENDIF() @@ -92,4 +97,5 @@ FUNCTION(BUILD_PLUGIN PLUGIN_NAME) SET_PROPERTY(GLOBAL APPEND PROPERTY PLUGINS_BUILT ${PLUGIN_NAME}) GET_PROPERTY(PLUGINS_BUILT GLOBAL PROPERTY PLUGINS_BUILT) -ENDFUNCTION(BUILD_PLUGIN) +ENDMACRO(BUILD_PLUGIN) + diff --git a/cmake/modules/DetectMachine.cmake b/cmake/modules/DetectMachine.cmake index 040b7ef203f..86807b7573c 100644 --- a/cmake/modules/DetectMachine.cmake +++ b/cmake/modules/DetectMachine.cmake @@ -1,5 +1,3 @@ -INCLUDE(CheckCXXSourceCompiles) - IF(WIN32) SET(LMMS_BUILD_WIN32 1) ELSEIF(APPLE) @@ -109,27 +107,3 @@ IF(LMMS_BUILD_APPLE) STRING(REGEX REPLACE "\\.[0-9]*$" "" APPLE_OS_VER "${APPLE_OS_VER}") SET(CMAKE_MACOSX_RPATH 1) ENDIF() - -# Detect MinGW -IF(WIN32 AND CMAKE_COMPILER_IS_GNUCXX) - SET(MINGW TRUE) -ENDIF() - -# Detect MINGW thread support -IF(MINGW) - CHECK_CXX_SOURCE_COMPILES(" - #include - #include - int main(int argc, const char* argv[]) { - std::mutex m; - std::this_thread::yield(); - return 0; - } - " HAS_STD_THREADS) - IF(NOT HAS_STD_THREADS) - SET(NEED_MINGW_THREADS_REPLACEMENT TRUE) - ELSE() - SET(NEED_MINGW_THREADS_REPLACEMENT FALSE) - ENDIF() - MESSAGE(NEED_MINGW_THREADS_REPLACEMENT ${NEED_MINGW_THREADS_REPLACEMENT}) -ENDIF() diff --git a/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake b/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake index bd68a89be03..2f78a441e7a 100644 --- a/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake +++ b/cmake/toolchains/common/Ubuntu-MinGW-W64.cmake @@ -5,16 +5,13 @@ set(CMAKE_C_COMPILER ${TOOLCHAIN_PREFIX}-gcc) set(CMAKE_CXX_COMPILER ${TOOLCHAIN_PREFIX}-g++) set(CMAKE_RC_COMPILER ${TOOLCHAIN_PREFIX}-windres) -set(MINGW_PREFIX /usr/${TOOLCHAIN_PREFIX}) - -set(CMAKE_FIND_ROOT_PATH ${MINGW_PREFIX}) +set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX}) SET(ENV{PKG_CONFIG} /usr/bin/${TOOLCHAIN_PREFIX}-pkg-config) IF(WIN64) SET(TOOLCHAIN_PREFIX32 ${CMAKE_SYSTEM_PROCESSOR32}-w64-mingw32) SET(CMAKE_C_COMPILER32 ${TOOLCHAIN_PREFIX32}-gcc) SET(CMAKE_CXX_COMPILER32 ${TOOLCHAIN_PREFIX32}-g++) - set(MINGW_PREFIX32 /usr/${TOOLCHAIN_PREFIX32}) ENDIF() INCLUDE(${CMAKE_CURRENT_LIST_DIR}/WinCrossCompile.cmake) diff --git a/include/AudioPort.h b/include/AudioPort.h index 1c1cf1064ba..146bbd192cd 100644 --- a/include/AudioPort.h +++ b/include/AudioPort.h @@ -30,7 +30,7 @@ #include #include -#include "Memory.h" +#include "MemoryManager.h" #include "PlayHandle.h" class EffectChain; diff --git a/include/AutomatableModel.h b/include/AutomatableModel.h index 0289a8d2d56..2091b3f9a86 100644 --- a/include/AutomatableModel.h +++ b/include/AutomatableModel.h @@ -32,7 +32,7 @@ #include "Model.h" #include "TimePos.h" #include "ValueBuffer.h" -#include "Memory.h" +#include "MemoryManager.h" #include "ModelVisitor.h" // simple way to map a property of a view to a model diff --git a/include/AutomationTrack.h b/include/AutomationTrack.h index 28be7a62365..b783c590559 100644 --- a/include/AutomationTrack.h +++ b/include/AutomationTrack.h @@ -31,7 +31,7 @@ #include "TrackView.h" -class LMMS_EXPORT AutomationTrack : public Track +class AutomationTrack : public Track { Q_OBJECT public: diff --git a/include/BBTrack.h b/include/BBTrack.h index f6567715ff0..4197a88daf0 100644 --- a/include/BBTrack.h +++ b/include/BBTrack.h @@ -31,7 +31,6 @@ #include #include -#include "lmms_export.h" #include "TrackContentObjectView.h" #include "Track.h" #include "TrackView.h" @@ -40,7 +39,7 @@ class TrackLabelButton; class TrackContainer; -class LMMS_EXPORT BBTCO : public TrackContentObject +class BBTCO : public TrackContentObject { public: BBTCO( Track * _track ); diff --git a/include/BasicFilters.h b/include/BasicFilters.h index 9a8e8191567..c3a76d36e0d 100644 --- a/include/BasicFilters.h +++ b/include/BasicFilters.h @@ -41,7 +41,7 @@ #include "lmms_basics.h" #include "lmms_constants.h" #include "interpolation.h" -#include "Memory.h" +#include "MemoryManager.h" template class BasicFilters; diff --git a/include/DataFile.h b/include/DataFile.h index ed947eef2be..5d6ead5adb3 100644 --- a/include/DataFile.h +++ b/include/DataFile.h @@ -30,7 +30,7 @@ #include #include "lmms_export.h" -#include "Memory.h" +#include "MemoryManager.h" #include "ProjectVersion.h" class QTextStream; diff --git a/include/Delay.h b/include/Delay.h index 7a709fd2c2c..0e32a7635b3 100644 --- a/include/Delay.h +++ b/include/Delay.h @@ -30,7 +30,7 @@ #include "lmms_basics.h" #include "lmms_math.h" #include "interpolation.h" -#include "Memory.h" +#include "MemoryManager.h" // brief usage diff --git a/include/DetuningHelper.h b/include/DetuningHelper.h index dbef4441e7a..2157b6ba828 100644 --- a/include/DetuningHelper.h +++ b/include/DetuningHelper.h @@ -27,7 +27,7 @@ #define DETUNING_HELPER_H #include "InlineAutomation.h" -#include "Memory.h" +#include "MemoryManager.h" class DetuningHelper : public InlineAutomation { diff --git a/include/Effect.h b/include/Effect.h index 93b6d45b2f9..3874aa602ca 100644 --- a/include/Effect.h +++ b/include/Effect.h @@ -31,7 +31,7 @@ #include "Mixer.h" #include "AutomatableModel.h" #include "TempoSyncKnobModel.h" -#include "Memory.h" +#include "MemoryManager.h" class EffectChain; class EffectControls; diff --git a/include/Instrument.h b/include/Instrument.h index 90364e84b30..eab218081e6 100644 --- a/include/Instrument.h +++ b/include/Instrument.h @@ -29,7 +29,7 @@ #include #include "lmms_export.h" #include "lmms_basics.h" -#include "Memory.h" +#include "MemoryManager.h" #include "Plugin.h" #include "TimePos.h" diff --git a/include/MainApplication.h b/include/MainApplication.h index bafa9baeb1e..d28900213c9 100644 --- a/include/MainApplication.h +++ b/include/MainApplication.h @@ -25,7 +25,6 @@ #ifndef MAINAPPLICATION_H #define MAINAPPLICATION_H -#include "lmms_export.h" #include "lmmsconfig.h" #include @@ -36,7 +35,7 @@ #endif #if defined(LMMS_BUILD_WIN32) -class LMMS_EXPORT MainApplication : public QApplication, public QAbstractNativeEventFilter +class MainApplication : public QApplication, public QAbstractNativeEventFilter #else class MainApplication : public QApplication #endif diff --git a/include/MainWindow.h b/include/MainWindow.h index 5acbbac2fb1..a179e651e49 100644 --- a/include/MainWindow.h +++ b/include/MainWindow.h @@ -25,8 +25,6 @@ #ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H -#include "lmms_export.h" - #include #include #include @@ -45,7 +43,7 @@ class PluginView; class ToolButton; -class LMMS_EXPORT MainWindow : public QMainWindow +class MainWindow : public QMainWindow { Q_OBJECT public: @@ -63,7 +61,7 @@ class LMMS_EXPORT MainWindow : public QMainWindow void addSpacingToToolBar( int _size ); // wrap the widget with a window decoration and add it to the workspace - SubWindow* addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags = QFlag(0)); + LMMS_EXPORT SubWindow* addWindowedWidget(QWidget *w, Qt::WindowFlags windowFlags = QFlag(0)); /// diff --git a/include/MemoryHelper.h b/include/MemoryHelper.h new file mode 100644 index 00000000000..7bd31bf2b68 --- /dev/null +++ b/include/MemoryHelper.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2014 Simon Symeonidis + * Copyright (c) 2004-2014 Tobias Doerffel + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + + +#ifndef MEMORY_HELPER_H +#define MEMORY_HELPER_H + +/** + * Helper class to alocate aligned memory and free it. + */ +class MemoryHelper { +public: + + static void* alignedMalloc( size_t ); + + static void alignedFree( void* ); + +private: +}; + +#endif + diff --git a/include/Memory.h b/include/MemoryManager.h similarity index 60% rename from include/Memory.h rename to include/MemoryManager.h index 5769e662329..4c225e026a9 100644 --- a/include/Memory.h +++ b/include/MemoryManager.h @@ -1,10 +1,9 @@ /* - * Memory.h + * MemoryManager.h * * Copyright (c) 2017 Lukas W - * Copyright (c) 2014 Simon Symeonidis * Copyright (c) 2014 Vesa Kivimäki - * Copyright (c) 2004-2014 Tobias Doerffel + * Copyright (c) 2007-2014 Tobias Doerffel * * This file is part of LMMS - https://lmms.io * @@ -32,36 +31,25 @@ #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; -static thread_local MemoryManager::MmCounter _mm_thread_counter; - template -class LMMS_EXPORT MmAllocator +struct 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 ) { @@ -76,36 +64,6 @@ class LMMS_EXPORT MmAllocator typedef std::vector > vector; }; -class _AlignedAllocator_Base -{ -protected: - void* alloc_impl( size_t alignment, size_t size ); - void dealloc_impl( void* p ); -}; - -template -class AlignedAllocator : _AlignedAllocator_Base -{ -public: - typedef T value_type; - template struct rebind { typedef AlignedAllocator other; }; - - AlignedAllocator( size_t alignment = 16 ) - : alignment(alignment) {} - - T* allocate( std::size_t n ) - { - return reinterpret_cast( alloc_impl( alignment, sizeof(T) * n ) ); - } - - void deallocate( T* p, std::size_t ) - { - dealloc_impl( p ); - } - -private: - std::size_t alignment; -}; #define MM_OPERATORS \ public: \ diff --git a/include/MidiEventProcessor.h b/include/MidiEventProcessor.h index ba94beea5e9..3ded20430d2 100644 --- a/include/MidiEventProcessor.h +++ b/include/MidiEventProcessor.h @@ -26,7 +26,7 @@ #define MIDI_EVENT_PROCESSOR_H #include "MidiEvent.h" -#include "Memory.h" +#include "MemoryManager.h" #include "TimePos.h" // all classes being able to process MIDI-events should inherit from this diff --git a/include/MixerProfiler.h b/include/MixerProfiler.h index 26b842dde68..0c46c34cb0d 100644 --- a/include/MixerProfiler.h +++ b/include/MixerProfiler.h @@ -27,11 +27,10 @@ #include -#include "lmms_export.h" #include "lmms_basics.h" #include "MicroTimer.h" -class LMMS_EXPORT MixerProfiler +class MixerProfiler { public: MixerProfiler(); diff --git a/include/ModelVisitor.h b/include/ModelVisitor.h index 5161718b446..f9d156e30f4 100644 --- a/include/ModelVisitor.h +++ b/include/ModelVisitor.h @@ -25,8 +25,6 @@ #ifndef MODELVISITOR_H #define MODELVISITOR_H -#include "lmms_export.h" - class AutomatableModel; class BoolModel; class IntModel; @@ -34,7 +32,7 @@ class FloatModel; class ComboBoxModel; class TempoSyncKnobModel; -class LMMS_EXPORT ModelVisitor +class ModelVisitor { template void up(ModelType& m) { visit(static_cast(m)); } @@ -48,7 +46,7 @@ class LMMS_EXPORT ModelVisitor virtual ~ModelVisitor(); }; -class LMMS_EXPORT ConstModelVisitor +class ConstModelVisitor { template void up(const ModelType& m) { diff --git a/include/PlayHandle.h b/include/PlayHandle.h index c3577c0076a..1ddd632d1c3 100644 --- a/include/PlayHandle.h +++ b/include/PlayHandle.h @@ -30,7 +30,7 @@ #include "lmms_export.h" -#include "Memory.h" +#include "MemoryManager.h" #include "ThreadableJob.h" #include "lmms_basics.h" diff --git a/include/Plugin.h b/include/Plugin.h index 3332b04bf1b..cb8995bf2cd 100644 --- a/include/Plugin.h +++ b/include/Plugin.h @@ -31,7 +31,7 @@ #include "JournallingObject.h" #include "Model.h" -#include "Memory.h" +#include "MemoryManager.h" class QWidget; diff --git a/include/ProjectVersion.h b/include/ProjectVersion.h index 00a639459dd..94ee9c6ba89 100644 --- a/include/ProjectVersion.h +++ b/include/ProjectVersion.h @@ -31,13 +31,12 @@ #include #include -#include "lmms_export.h" /*! \brief Version number parsing and comparison * * Parses and compares version information. i.e. "1.0.3" < "1.0.10" */ -class LMMS_EXPORT ProjectVersion +class ProjectVersion { public: enum CompareType : int { None = 0, Major=1, Minor=2, Release=3, Stage=4, Build=5, All = std::numeric_limits::max() }; diff --git a/include/RenderManager.h b/include/RenderManager.h index cd4879fece7..01236d7476a 100644 --- a/include/RenderManager.h +++ b/include/RenderManager.h @@ -32,7 +32,7 @@ #include "OutputSettings.h" -class LMMS_EXPORT RenderManager : public QObject +class RenderManager : public QObject { Q_OBJECT public: diff --git a/include/RingBuffer.h b/include/RingBuffer.h index 8b088d8ef83..c7e91bd3392 100644 --- a/include/RingBuffer.h +++ b/include/RingBuffer.h @@ -30,7 +30,7 @@ #include #include "lmms_basics.h" #include "lmms_math.h" -#include "Memory.h" +#include "MemoryManager.h" /** \brief A basic LMMS ring buffer for single-thread use. For thread and realtime safe alternative see LocklessRingBuffer. */ diff --git a/include/SampleBuffer.h b/include/SampleBuffer.h index 6785e0a9092..75b90e01708 100644 --- a/include/SampleBuffer.h +++ b/include/SampleBuffer.h @@ -36,7 +36,7 @@ #include "lmms_basics.h" #include "lmms_math.h" #include "shared_object.h" -#include "Memory.h" +#include "MemoryManager.h" class QPainter; diff --git a/include/ValueBuffer.h b/include/ValueBuffer.h index 5f847f63260..f9869de8888 100644 --- a/include/ValueBuffer.h +++ b/include/ValueBuffer.h @@ -28,7 +28,7 @@ #include -#include "Memory.h" +#include "MemoryManager.h" #include "lmms_export.h" class LMMS_EXPORT ValueBuffer : public std::vector diff --git a/plugins/FreeBoy/Gb_Apu_Buffer.h b/plugins/FreeBoy/Gb_Apu_Buffer.h index 01e44fbcd78..5228b7b8afd 100644 --- a/plugins/FreeBoy/Gb_Apu_Buffer.h +++ b/plugins/FreeBoy/Gb_Apu_Buffer.h @@ -25,7 +25,7 @@ #include "Gb_Apu.h" #include "Multi_Buffer.h" -#include "Memory.h" +#include "MemoryManager.h" class Gb_Apu_Buffer : public Gb_Apu { MM_OPERATORS diff --git a/plugins/GigPlayer/GigPlayer.h b/plugins/GigPlayer/GigPlayer.h index 49465be2ae9..b9467b91bbf 100644 --- a/plugins/GigPlayer/GigPlayer.h +++ b/plugins/GigPlayer/GigPlayer.h @@ -38,7 +38,7 @@ #include "Knob.h" #include "LcdSpinBox.h" #include "LedCheckbox.h" -#include "Memory.h" +#include "MemoryManager.h" #include "gig.h" class GigInstrumentView; diff --git a/plugins/LadspaEffect/LadspaEffect.cpp b/plugins/LadspaEffect/LadspaEffect.cpp index 79a3c102736..117e1e0e10e 100644 --- a/plugins/LadspaEffect/LadspaEffect.cpp +++ b/plugins/LadspaEffect/LadspaEffect.cpp @@ -38,7 +38,7 @@ #include "EffectChain.h" #include "AutomationPattern.h" #include "ControllerConnection.h" -#include "Memory.h" +#include "MemoryManager.h" #include "ValueBuffer.h" #include "Song.h" diff --git a/plugins/LadspaEffect/calf/CMakeLists.txt b/plugins/LadspaEffect/calf/CMakeLists.txt index 4b264ea1a1d..f5fb632f6ad 100644 --- a/plugins/LadspaEffect/calf/CMakeLists.txt +++ b/plugins/LadspaEffect/calf/CMakeLists.txt @@ -47,5 +47,3 @@ ENDIF() IF(NOT LMMS_BUILD_APPLE AND NOT LMMS_BUILD_OPENBSD) SET_TARGET_PROPERTIES(veal PROPERTIES LINK_FLAGS "${LINK_FLAGS} -shared -Wl,-no-undefined") ENDIF() - -TARGET_LINK_LIBRARIES(veal lmmslib) diff --git a/plugins/Xpressive/ExprSynth.h b/plugins/Xpressive/ExprSynth.h index 01e98ebe923..bb25fd036dd 100644 --- a/plugins/Xpressive/ExprSynth.h +++ b/plugins/Xpressive/ExprSynth.h @@ -31,7 +31,7 @@ #include "AutomatableModel.h" #include "Graph.h" #include "Instrument.h" -#include "Memory.h" +#include "MemoryManager.h" class ExprFrontData; diff --git a/plugins/bit_invader/bit_invader.h b/plugins/bit_invader/bit_invader.h index 88ba8cf08c9..ae9c92cb264 100644 --- a/plugins/bit_invader/bit_invader.h +++ b/plugins/bit_invader/bit_invader.h @@ -33,7 +33,7 @@ #include "Knob.h" #include "PixmapButton.h" #include "LedCheckbox.h" -#include "Memory.h" +#include "MemoryManager.h" class oscillator; class bitInvaderView; diff --git a/plugins/kicker/CMakeLists.txt b/plugins/kicker/CMakeLists.txt index 1334d11aa33..0ac9f87b50b 100644 --- a/plugins/kicker/CMakeLists.txt +++ b/plugins/kicker/CMakeLists.txt @@ -1,3 +1,3 @@ INCLUDE(BuildPlugin) -BUILD_PLUGIN(kicker kicker.cpp kicker.h KickerOsc.h MOCFILES kicker.h EMBEDDED_RESOURCES artwork.png logo.png) +BUILD_PLUGIN(kicker kicker.cpp kicker.h MOCFILES kicker.h EMBEDDED_RESOURCES artwork.png logo.png) diff --git a/plugins/kicker/KickerOsc.h b/plugins/kicker/KickerOsc.h index 4fd66a6bb33..1375725b32e 100644 --- a/plugins/kicker/KickerOsc.h +++ b/plugins/kicker/KickerOsc.h @@ -31,7 +31,7 @@ #include "lmms_math.h" #include "interpolation.h" -#include "Memory.h" +#include "MemoryManager.h" template diff --git a/plugins/nes/Nes.h b/plugins/nes/Nes.h index 9e093b5334b..bbf326d3271 100644 --- a/plugins/nes/Nes.h +++ b/plugins/nes/Nes.h @@ -34,7 +34,7 @@ #include "TempoSyncKnob.h" #include "NotePlayHandle.h" #include "PixmapButton.h" -#include "Memory.h" +#include "MemoryManager.h" #define makeknob( name, x, y, hint, unit, oname ) \ diff --git a/plugins/patman/patman.h b/plugins/patman/patman.h index 5b7f6fd6546..8d5689b7363 100644 --- a/plugins/patman/patman.h +++ b/plugins/patman/patman.h @@ -30,7 +30,7 @@ #include "InstrumentView.h" #include "SampleBuffer.h" #include "AutomatableModel.h" -#include "Memory.h" +#include "MemoryManager.h" class PixmapButton; diff --git a/plugins/sf2_player/sf2_player.h b/plugins/sf2_player/sf2_player.h index 8127d62329e..1dde587ad5e 100644 --- a/plugins/sf2_player/sf2_player.h +++ b/plugins/sf2_player/sf2_player.h @@ -37,7 +37,7 @@ #include "LcdSpinBox.h" #include "LedCheckbox.h" #include "fluidsynthshims.h" -#include "Memory.h" +#include "MemoryManager.h" class sf2InstrumentView; class sf2Font; diff --git a/plugins/sfxr/sfxr.h b/plugins/sfxr/sfxr.h index 1214aeb37a1..20ae54c96fe 100644 --- a/plugins/sfxr/sfxr.h +++ b/plugins/sfxr/sfxr.h @@ -34,7 +34,7 @@ #include "Graph.h" #include "PixmapButton.h" #include "LedCheckbox.h" -#include "Memory.h" +#include "MemoryManager.h" enum SfxrWaves diff --git a/plugins/vestige/vestige.cpp b/plugins/vestige/vestige.cpp index 77efcb8babd..d76ac37f6e5 100644 --- a/plugins/vestige/vestige.cpp +++ b/plugins/vestige/vestige.cpp @@ -40,6 +40,7 @@ #include +#include "BufferManager.h" #include "ConfigManager.h" #include "Engine.h" #include "FileDialog.h" diff --git a/plugins/vibed/string_container.h b/plugins/vibed/string_container.h index 08ab7879854..f615080790e 100644 --- a/plugins/vibed/string_container.h +++ b/plugins/vibed/string_container.h @@ -27,7 +27,7 @@ #include #include "vibrating_string.h" -#include "Memory.h" +#include "MemoryManager.h" class stringContainer diff --git a/plugins/watsyn/Watsyn.h b/plugins/watsyn/Watsyn.h index 1dd6f6b87e8..079e532e41a 100644 --- a/plugins/watsyn/Watsyn.h +++ b/plugins/watsyn/Watsyn.h @@ -35,7 +35,7 @@ #include "NotePlayHandle.h" #include "PixmapButton.h" #include -#include "Memory.h" +#include "MemoryManager.h" #define makeknob( name, x, y, hint, unit, oname ) \ diff --git a/src/3rdparty/rpmalloc/CMakeLists.txt b/src/3rdparty/rpmalloc/CMakeLists.txt index 96018fa8fbd..047c32678c2 100644 --- a/src/3rdparty/rpmalloc/CMakeLists.txt +++ b/src/3rdparty/rpmalloc/CMakeLists.txt @@ -7,10 +7,7 @@ target_include_directories(rpmalloc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/rpmalloc/rpmalloc ) -set_target_properties(rpmalloc PROPERTIES - C_STANDARD 11 - POSITION_INDEPENDENT_CODE ON -) +set_property(TARGET rpmalloc PROPERTY C_STANDARD 11) IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") target_compile_options(rpmalloc diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b6e0376c195..94752a650c0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -21,6 +21,14 @@ ADD_SUBDIRECTORY(gui) ADD_SUBDIRECTORY(tracks) QT5_WRAP_UI(LMMS_UI_OUT ${LMMS_UIS}) +INCLUDE_DIRECTORIES( + "${CMAKE_CURRENT_BINARY_DIR}" + "${CMAKE_BINARY_DIR}" + "${CMAKE_BINARY_DIR}/include" + "${CMAKE_SOURCE_DIR}" + "${CMAKE_SOURCE_DIR}/include" + "${RINGBUFFER_DIR}/include" +) IF(WIN32 AND MSVC) SET(WINRC "${CMAKE_BINARY_DIR}/lmms.rc") @@ -41,6 +49,60 @@ ADD_GEN_QRC(LMMS_RCC_OUT lmms.qrc "${CONTRIBUTORS}" ) +# Paths relative to lmms executable +FILE(RELATIVE_PATH LIB_DIR_RELATIVE "/${BIN_DIR}" "/${LIB_DIR}") +FILE(RELATIVE_PATH PLUGIN_DIR_RELATIVE "/${BIN_DIR}" "/${PLUGIN_DIR}") +ADD_DEFINITIONS(-DLIB_DIR="${LIB_DIR_RELATIVE}" -DPLUGIN_DIR="${PLUGIN_DIR_RELATIVE}" ${PULSEAUDIO_DEFINITIONS} ${PORTAUDIO_DEFINITIONS}) +INCLUDE_DIRECTORIES( + ${JACK_INCLUDE_DIRS} + ${SAMPLERATE_INCLUDE_DIRS} + ${SNDFILE_INCLUDE_DIRS} + ${SNDIO_INCLUDE_DIRS} + ${FFTW3F_INCLUDE_DIRS} +) + +IF(NOT ("${SDL2_INCLUDE_DIR}" STREQUAL "")) + INCLUDE_DIRECTORIES("${SDL2_INCLUDE_DIR}") +ELSEIF(NOT ("${SDL_INCLUDE_DIR}" STREQUAL "")) + INCLUDE_DIRECTORIES("${SDL_INCLUDE_DIR}") +ENDIF() + +IF(LMMS_HAVE_WEAKJACK) + LIST(APPEND LMMS_SRCS "${WEAKJACK_INCLUDE_DIRS}/weak_libjack.c") + LIST(APPEND LMMS_INCLUDES "${WEAKJACK_INCLUDE_DIRS}/weak_libjack.h") + INCLUDE_DIRECTORIES("${WEAKJACK_INCLUDE_DIRS}") + ADD_DEFINITIONS(-DUSE_WEAK_JACK=1 -DNO_JACK_METADATA=1) +ENDIF() + +IF(NOT ("${PORTAUDIO_INCLUDE_DIR}" STREQUAL "")) + INCLUDE_DIRECTORIES("${PORTAUDIO_INCLUDE_DIR}") +ENDIF() + +IF(NOT ("${PULSEAUDIO_INCLUDE_DIR}" STREQUAL "")) + INCLUDE_DIRECTORIES("${PULSEAUDIO_INCLUDE_DIR}") +ENDIF() + +IF(NOT ("${OGGVORBIS_INCLUDE_DIR}" STREQUAL "")) + INCLUDE_DIRECTORIES("${OGGVORBIS_INCLUDE_DIR}") +ENDIF() + +IF(NOT ("${LAME_INCLUDE_DIRS}" STREQUAL "")) + INCLUDE_DIRECTORIES("${LAME_INCLUDE_DIRS}") +ENDIF() + +IF(NOT ("${LV2_INCLUDE_DIRS}" STREQUAL "")) + INCLUDE_DIRECTORIES(${LV2_INCLUDE_DIRS}) +ENDIF() + +IF(NOT ("${LILV_INCLUDE_DIRS}" STREQUAL "")) + INCLUDE_DIRECTORIES(${LILV_INCLUDE_DIRS}) +ENDIF() + +IF(NOT ("${SUIL_INCLUDE_DIRS}" STREQUAL "")) + INCLUDE_DIRECTORIES(${SUIL_INCLUDE_DIRS}) +ENDIF() +LIST(APPEND LMMS_SRCS "${RINGBUFFER_DIR}/src/lib/ringbuffer.cpp") + # Use libraries in non-standard directories (e.g., another version of Qt) IF(LMMS_BUILD_LINUX) LINK_LIBRARIES(-Wl,--enable-new-dtags) @@ -48,63 +110,35 @@ IF(LMMS_BUILD_LINUX) ENDIF() SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) -ADD_LIBRARY(lmmslib SHARED +ADD_LIBRARY(lmmsobjs OBJECT ${LMMS_SRCS} ${LMMS_INCLUDES} ${LMMS_UI_OUT} ${LMMS_RCC_OUT} - ${RINGBUFFER_DIR}/src/lib/ringbuffer.cpp - $<$: - ${WEAKJACK_INCLUDE_DIR}/weak_libjack.c - ${WEAKJACK_INCLUDE_DIR}/weak_libjack.h - > ) -GENERATE_EXPORT_HEADER(lmmslib +GENERATE_EXPORT_HEADER(lmmsobjs BASE_NAME lmms ) ADD_EXECUTABLE(lmms core/main.cpp + $ "${WINRC}" ) - -TARGET_INCLUDE_DIRECTORIES(lmmslib PUBLIC - "${CMAKE_CURRENT_BINARY_DIR}" - "${CMAKE_BINARY_DIR}" - "${CMAKE_BINARY_DIR}/include" - "${CMAKE_SOURCE_DIR}" - "${CMAKE_SOURCE_DIR}/include" - "${RINGBUFFER_DIR}/include" - ${JACK_INCLUDE_DIRS} - ${SAMPLERATE_INCLUDE_DIRS} - ${SNDFILE_INCLUDE_DIRS} - ${SNDIO_INCLUDE_DIRS} - ${FFTW3F_INCLUDE_DIRS} - ${SDL2_INCLUDE_DIR} - ${SDL_INCLUDE_DIR} - ${PORTAUDIO_INCLUDE_DIR} - ${PULSEAUDIO_INCLUDE_DIR} - ${OGGVORBIS_INCLUDE_DIR} - ${LAME_INCLUDE_DIRS} - ${LV2_INCLUDE_DIRS} - ${LILV_INCLUDE_DIRS} - ${SUIL_INCLUDE_DIRS} - ${WEAKJACK_INCLUDE_DIR} +TARGET_INCLUDE_DIRECTORIES(lmms + PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ) - -# Paths relative to lmms executable -FILE(RELATIVE_PATH LIB_DIR_RELATIVE "/${BIN_DIR}" "/${LIB_DIR}") -FILE(RELATIVE_PATH PLUGIN_DIR_RELATIVE "/${BIN_DIR}" "/${PLUGIN_DIR}") -TARGET_COMPILE_DEFINITIONS(lmmslib - PRIVATE - LIB_DIR="${LIB_DIR_RELATIVE}" - PLUGIN_DIR="${PLUGIN_DIR_RELATIVE}" - PUBLIC - ${PULSEAUDIO_DEFINITIONS} - ${PORTAUDIO_DEFINITIONS} - $<$:USE_WEAK_JACK=1 NO_JACK_METADATA=1> +# CMake doesn't define target_EXPORTS for OBJECT libraries. +# See the documentation of DEFINE_SYMBOL for details. +# Also add LMMS_STATIC_DEFINE for targets linking against it. +TARGET_COMPILE_DEFINITIONS(lmmsobjs + PRIVATE -Dlmmsobjs_EXPORTS + INTERFACE -DLMMS_STATIC_DEFINE +) +TARGET_COMPILE_DEFINITIONS(lmms + PRIVATE $ ) # Set Visual Studio startup project to lmms @@ -131,7 +165,7 @@ IF(LMMS_BUILD_HAIKU) SET(EXTRA_LIBRARIES "-lnetwork") ENDIF() -TARGET_LINK_LIBRARIES(lmmslib +SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} ${CMAKE_THREAD_LIBS_INIT} ${QT_LIBRARIES} ${ASOUND_LIBRARY} @@ -153,9 +187,39 @@ TARGET_LINK_LIBRARIES(lmmslib rpmalloc cds ) -TARGET_LINK_LIBRARIES(lmms lmmslib) -IF(NOT LMMS_BUILD_WIN32) +# Expose required libs for tests binary +SET(LMMS_REQUIRED_LIBS ${LMMS_REQUIRED_LIBS} PARENT_SCOPE) + +TARGET_LINK_LIBRARIES(lmms + ${LMMS_REQUIRED_LIBS} +) + +FOREACH(LIB ${LMMS_REQUIRED_LIBS}) + IF(TARGET ${LIB}) + GET_TARGET_PROPERTY(INCLUDE_DIRS ${LIB} INTERFACE_INCLUDE_DIRECTORIES) + IF(INCLUDE_DIRS) + TARGET_INCLUDE_DIRECTORIES(lmmsobjs PRIVATE ${INCLUDE_DIRS}) + ENDIF() + ENDIF() +ENDFOREACH() + +IF(LMMS_BUILD_WIN32) + SET_TARGET_PROPERTIES(lmms PROPERTIES + ENABLE_EXPORTS ON + ) + IF(LMMS_BUILD_MSYS) + # ENABLE_EXPORTS property has no effect in some MSYS2 configurations. + # Add the linker flag manually to create liblmms.dll.a import library + SET_PROPERTY(TARGET lmms + APPEND_STRING PROPERTY LINK_FLAGS " -Wl,--out-implib,liblmms.dll.a" + ) + ENDIF() +ELSE() + IF(NOT LMMS_BUILD_APPLE) + SET_TARGET_PROPERTIES(lmms PROPERTIES LINK_FLAGS "${LINK_FLAGS} -Wl,-E") + ENDIF(NOT LMMS_BUILD_APPLE) + if(CMAKE_INSTALL_MANDIR) SET(INSTALL_MANDIR ${CMAKE_INSTALL_MANDIR}) ELSE(CMAKE_INSTALL_MANDIR) @@ -166,7 +230,4 @@ IF(NOT LMMS_BUILD_WIN32) PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) ENDIF() -INSTALL(TARGETS lmms lmmslib - RUNTIME DESTINATION "${BIN_DIR}" - LIBRARY DESTINATION "${LIB_DIR}" -) +INSTALL(TARGETS lmms RUNTIME DESTINATION "${BIN_DIR}") diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 6c043b5396c..754ab4a183e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -32,7 +32,8 @@ set(LMMS_SRCS core/LadspaManager.cpp core/LfoController.cpp core/LinkedModelGroups.cpp - core/Memory.cpp + core/MemoryHelper.cpp + core/MemoryManager.cpp core/MemoryPool.cpp core/MeterModel.cpp core/MicroTimer.cpp diff --git a/src/core/InstrumentFunctions.cpp b/src/core/InstrumentFunctions.cpp index c5b4daa5296..a98d519ee41 100644 --- a/src/core/InstrumentFunctions.cpp +++ b/src/core/InstrumentFunctions.cpp @@ -31,6 +31,7 @@ #include "Mixer.h" #include "PresetPreviewPlayHandle.h" + InstrumentFunctionNoteStacking::ChordTable::Init InstrumentFunctionNoteStacking::ChordTable::s_initTable[] = { { QT_TRANSLATE_NOOP( "InstrumentFunctionNoteStacking", "octave" ), { 0, -1 } }, diff --git a/src/core/MemoryHelper.cpp b/src/core/MemoryHelper.cpp new file mode 100644 index 00000000000..eb5a24d4449 --- /dev/null +++ b/src/core/MemoryHelper.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2014 Simon Symeonidis + * Copyright (c) 2008-2014 Tobias Doerffel + * + * This file is part of LMMS - https://lmms.io + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include + +#include "lmms_basics.h" +#include "MemoryHelper.h" + +/** + * Allocate a number of bytes and return them. + * @param byteNum is the number of bytes + */ +void* MemoryHelper::alignedMalloc( size_t byteNum ) +{ + char *ptr, *ptr2, *aligned_ptr; + int align_mask = ALIGN_SIZE - 1; + + ptr = static_cast( malloc( byteNum + ALIGN_SIZE + sizeof( int ) ) ); + + if( ptr == NULL ) return NULL; + + ptr2 = ptr + sizeof( int ); + aligned_ptr = ptr2 + ( ALIGN_SIZE - ( ( size_t ) ptr2 & align_mask ) ); + + ptr2 = aligned_ptr - sizeof( int ); + *( ( int* ) ptr2 ) = ( int )( aligned_ptr - ptr ); + + return aligned_ptr; +} + + +/** + * Free an aligned buffer + * @param _buffer is the buffer to free + */ +void MemoryHelper::alignedFree( void* _buffer ) +{ + if( _buffer ) + { + int *ptr2 = static_cast( _buffer ) - 1; + _buffer = static_cast( _buffer ) - *ptr2; + free( _buffer ); + } +} + diff --git a/src/core/Memory.cpp b/src/core/MemoryManager.cpp similarity index 67% rename from src/core/Memory.cpp rename to src/core/MemoryManager.cpp index bd8b1ca80c6..d0932e4f17b 100644 --- a/src/core/Memory.cpp +++ b/src/core/MemoryManager.cpp @@ -1,9 +1,7 @@ /* - * Memory.cpp + * MemoryManager.cpp * - * Copyright (c) 2018 Lukas W - * Copyright (c) 2014 Simon Symeonidis - * Copyright (c) 2004-2014 Tobias Doerffel + * Copyright (c) 2017 Lukas W * * This file is part of LMMS - https://lmms.io * @@ -25,11 +23,40 @@ */ -#include "Memory.h" +#include "MemoryManager.h" #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) @@ -48,33 +75,3 @@ void MemoryManager::free(void * ptr) Q_ASSERT_X(rpmalloc_is_thread_initialized(), "MemoryManager::free", "Thread not initialized"); 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 alignment, size_t size ) -{ - return rpaligned_alloc(alignment, size); -} - -void _AlignedAllocator_Base::dealloc_impl(void* p) -{ - rpfree(p); -} diff --git a/src/core/MemoryPool.cpp b/src/core/MemoryPool.cpp index fce0c14df77..de43dfebd54 100644 --- a/src/core/MemoryPool.cpp +++ b/src/core/MemoryPool.cpp @@ -17,7 +17,7 @@ #include "libcds.h" #include -#include "Memory.h" +#include "MemoryManager.h" class _MemoryPool_Private : MmAllocator { diff --git a/src/core/Mixer.cpp b/src/core/Mixer.cpp index a3ba9093774..32d337a4f05 100644 --- a/src/core/Mixer.cpp +++ b/src/core/Mixer.cpp @@ -36,7 +36,7 @@ #include "NotePlayHandle.h" #include "ConfigManager.h" #include "SamplePlayHandle.h" -#include "Memory.h" +#include "MemoryHelper.h" #include "MixHelpers.h" #include "BufferPool.h" @@ -136,9 +136,9 @@ Mixer::Mixer( bool renderOnly ) : // now that framesPerPeriod is fixed initialize global BufferPool BufferPool::init( m_framesPerPeriod ); - AlignedAllocator alloc; - m_outputBufferRead = alloc.allocate(m_framesPerPeriod); - m_outputBufferWrite = alloc.allocate(m_framesPerPeriod); + int outputBufferSize = m_framesPerPeriod * sizeof(surroundSampleFrame); + m_outputBufferRead = static_cast(MemoryHelper::alignedMalloc(outputBufferSize)); + m_outputBufferWrite = static_cast(MemoryHelper::alignedMalloc(outputBufferSize)); MixHelpers::clear(m_outputBufferRead, m_framesPerPeriod); MixHelpers::clear(m_outputBufferWrite, m_framesPerPeriod); @@ -182,9 +182,8 @@ Mixer::~Mixer() delete m_midiClient; delete m_audioDev; - AlignedAllocator alloc; - alloc.deallocate(m_outputBufferRead, m_framesPerPeriod); - alloc.deallocate(m_outputBufferWrite, m_framesPerPeriod); + MemoryHelper::alignedFree(m_outputBufferRead); + MemoryHelper::alignedFree(m_outputBufferWrite); for( int i = 0; i < 2; ++i ) { diff --git a/src/core/NotePlayHandle.cpp b/src/core/NotePlayHandle.cpp index 0912f2926fb..b483a0c4e84 100644 --- a/src/core/NotePlayHandle.cpp +++ b/src/core/NotePlayHandle.cpp @@ -32,6 +32,7 @@ #include "Mixer.h" #include "Song.h" + NotePlayHandle::BaseDetuning::BaseDetuning( DetuningHelper *detuning ) : m_value( detuning ? detuning->automationPattern()->valueAt( 0 ) : 0 ) { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 094ee974384..303633d37ec 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -6,8 +6,6 @@ INCLUDE_DIRECTORIES("${CMAKE_BINARY_DIR}/src") SET(CMAKE_CXX_STANDARD 14) -FIND_PACKAGE(Qt5Test) - SET(CMAKE_AUTOMOC ON) # FIXME: remove this once we export include directories for LMMS @@ -19,6 +17,7 @@ ADD_EXECUTABLE(tests EXCLUDE_FROM_ALL main.cpp QTestSuite + $ src/core/AutomatableModelTest.cpp src/core/ProjectVersionTest.cpp @@ -27,4 +26,8 @@ ADD_EXECUTABLE(tests src/tracks/AutomationTrackTest.cpp ) -TARGET_LINK_LIBRARIES(tests lmmslib Qt5::Test) +TARGET_COMPILE_DEFINITIONS(tests + PRIVATE $ +) +TARGET_LINK_LIBRARIES(tests ${QT_LIBRARIES} ${QT_QTTEST_LIBRARY}) +TARGET_LINK_LIBRARIES(tests ${LMMS_REQUIRED_LIBS}) From 7ce62fe0cb6c7619a7d220e9888e27afc74cc1cc Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Thu, 3 Oct 2024 19:48:14 +0900 Subject: [PATCH 26/28] Always build libcds as a static library --- src/3rdparty/CMakeLists.txt | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/src/3rdparty/CMakeLists.txt b/src/3rdparty/CMakeLists.txt index 50a8fff1f90..77a83d27b2c 100644 --- a/src/3rdparty/CMakeLists.txt +++ b/src/3rdparty/CMakeLists.txt @@ -11,17 +11,6 @@ target_include_directories(jack_headers INTERFACE jack2/common) ADD_SUBDIRECTORY(hiir) ADD_SUBDIRECTORY(weakjack) -IF(WIN32 AND CMAKE_COMPILER_IS_GNUCXX) - SET(MINGW TRUE) -ENDIF() - -IF(MINGW) - # Work around linking errors with MinGW - SET(CDS_LIBRARY_TYPE SHARED) -ELSE() - SET(CDS_LIBRARY_TYPE STATIC) -ENDIF() - ADD_LIBRARY(cds ${CDS_LIBRARY_TYPE} libcds/src/init.cpp libcds/src/hp.cpp @@ -42,17 +31,9 @@ TARGET_INCLUDE_DIRECTORIES(cds PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/libcds" ) -IF(CDS_LIBRARY_TYPE STREQUAL "STATIC") - TARGET_COMPILE_DEFINITIONS(cds - PUBLIC CDS_BUILD_STATIC_LIB - ) -ELSE() - TARGET_COMPILE_DEFINITIONS(cds - PRIVATE CDS_BUILD_LIB - ) - # Install DLL - install(TARGETS cds RUNTIME DESTINATION .) -ENDIF() +TARGET_COMPILE_DEFINITIONS(cds + PUBLIC CDS_BUILD_STATIC_LIB +) # The lockless ring buffer library is linked as part of the core add_library(ringbuffer OBJECT From 7782954e6e032abaa6585359b6acc2d98acc14b8 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Thu, 3 Oct 2024 20:32:55 +0900 Subject: [PATCH 27/28] Fix namespace --- include/NiftyCounter.h | 5 +++++ include/libcds.h | 6 +++--- src/core/libcds.cpp | 4 ++-- tests/scripted/check-namespace | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/NiftyCounter.h b/include/NiftyCounter.h index 3b333c58f3f..d5b618407f8 100644 --- a/include/NiftyCounter.h +++ b/include/NiftyCounter.h @@ -12,6 +12,9 @@ #pragma once +namespace lmms +{ + /// Nifty counter, also known as "Schwarz Counter". Used for ensuring global /// static object initialization and destruction order. @@ -58,3 +61,5 @@ template class NiftyCounterTL : public _NiftyCounterCD_Base thread_local static int s_count; }; template thread_local int NiftyCounterTL::s_count = 0; + +} // namespace lmms diff --git a/include/libcds.h b/include/libcds.h index ac051ca00a1..91d41896380 100644 --- a/include/libcds.h +++ b/include/libcds.h @@ -9,7 +9,7 @@ # include "mingw-std-threads/mutex" #endif -namespace _cdslib +namespace lmms::_cdslib { void init(); void deinit(); @@ -18,6 +18,6 @@ namespace _cdslib static NiftyCounter _counter; static thread_local NiftyCounterTL<_cdslib::thread_init, _cdslib::thread_deinit> _thread_counter; -} +} // namespace lmms:_cdslib -#define CDS_THREAD_GUARD() (void)_cdslib::_thread_counter; +#define CDS_THREAD_GUARD() (void)lmms::_cdslib::_thread_counter; diff --git a/src/core/libcds.cpp b/src/core/libcds.cpp index d727b3022e1..c019db334d8 100644 --- a/src/core/libcds.cpp +++ b/src/core/libcds.cpp @@ -4,7 +4,7 @@ #include -namespace _cdslib +namespace lmms::_cdslib { void init() @@ -31,4 +31,4 @@ void thread_deinit() } } -} +} // namespace lmms::_cdslib diff --git a/tests/scripted/check-namespace b/tests/scripted/check-namespace index a816f0d7bd5..3394e583857 100755 --- a/tests/scripted/check-namespace +++ b/tests/scripted/check-namespace @@ -55,7 +55,7 @@ if not Path('.gitmodules').is_file(): print('You need to call this script from the LMMS top directory') exit(1) -result = subprocess.run(['git', 'ls-files', '*.[ch]', '*.[ch]pp', ':!tests/*'], +result = subprocess.run(['git', 'ls-files', '*.[ch]', '*.[ch]pp', ':!tests/*', ':!benchmarks/*'], capture_output=True, text=True, check=True) known_no_namespace_lmms = { From f54ac456dd5db055dd0305ccf8c469af5a4d9ad9 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Thu, 3 Oct 2024 20:34:08 +0900 Subject: [PATCH 28/28] Remove leftover of mingw-std-threads --- include/libcds.h | 5 ----- include/mingw-std-threads/mutex | 1 - include/mingw-std-threads/thread | 1 - 3 files changed, 7 deletions(-) delete mode 100644 include/mingw-std-threads/mutex delete mode 100644 include/mingw-std-threads/thread diff --git a/include/libcds.h b/include/libcds.h index 91d41896380..64754b94105 100644 --- a/include/libcds.h +++ b/include/libcds.h @@ -4,11 +4,6 @@ #include "NiftyCounter.h" -#if defined(__MINGW32__) && !defined(_GLIBCXX_HAS_GTHREADS) -# include "mingw-std-threads/thread" -# include "mingw-std-threads/mutex" -#endif - namespace lmms::_cdslib { void init(); diff --git a/include/mingw-std-threads/mutex b/include/mingw-std-threads/mutex deleted file mode 100644 index afeaf55b138..00000000000 --- a/include/mingw-std-threads/mutex +++ /dev/null @@ -1 +0,0 @@ -#include "mingw.mutex.h" diff --git a/include/mingw-std-threads/thread b/include/mingw-std-threads/thread deleted file mode 100644 index 0108f8ad70c..00000000000 --- a/include/mingw-std-threads/thread +++ /dev/null @@ -1 +0,0 @@ -#include "mingw.thread.h"