diff --git a/src/Audacity.h b/src/Audacity.h index c2b4523a2..3637ab2ca 100644 --- a/src/Audacity.h +++ b/src/Audacity.h @@ -170,9 +170,6 @@ void QuitAudacity(); // Marks strings for extraction only...must use wxGetTranslation() to translate. #define XO(s) wxT(s) -#include -#include - // This renames a good use of this C++ keyword that we don't need to review when hunting for leaks. #define PROHIBITED = delete @@ -182,178 +179,4 @@ void QuitAudacity(); // pointer like std::unique_ptr or std::shared_ptr. #define safenew new -#if !defined(__WXMSW__) -/* replicate the very useful C++14 make_unique for those build environments - that don't implement it yet. - - typical useage: - - auto p = std::make_unique(ctorArg1, ctorArg2, ... ctorArgN); - p->DoSomething(); - auto q = std::make_unique(count); - q[0].DoSomethingElse(); - - The first hides naked NEW and DELETE from the source code. - The second hides NEW[] and DELETE[]. Both of course ensure destruction if - you don't use something like std::move(p) or q.release(). Both expressions require - that you identify the type only once, which is brief and less error prone. - - (Whereas this omission of [] might invite a runtime error: - std::unique_ptr q { new Myclass[count] }; ) - - Some C++11 tricks needed here are (1) variadic argument lists and - (2) making the compile-time dispatch work correctly. You can't have - a partially specialized template function, but you get the effect of that - by other metaprogramming means. -*/ - -namespace std { - // For overloading resolution - template struct __make_unique_result { - using scalar_case = unique_ptr; - }; - - // Partial specialization of the struct for array case - template struct __make_unique_result { - using array_case = unique_ptr; - using element = X; - }; - - // Now the scalar version of unique_ptr - template inline - typename __make_unique_result::scalar_case - make_unique(Args&&... args) - { - return typename __make_unique_result::scalar_case - { safenew X( forward(args)... ) }; - } - - // Now the array version of unique_ptr - // The compile-time dispatch trick is that the non-existence - // of the scalar_case type makes the above overload - // unavailable when the template parameter is explicit - template inline - typename __make_unique_result::array_case - make_unique(size_t count) - { - return typename __make_unique_result::array_case - { safenew typename __make_unique_result::element[count] }; - } -} -#endif - -/* -* template class Maybe -* Can be used for monomorphic objects that are stack-allocable, but only conditionally constructed. -* You might also use it as a member. -* Initialize with create(), then use like a smart pointer, -* with *, ->, get(), reset(), or in if() -*/ - -template -class Maybe { -public: - - // Construct as NULL - Maybe() {} - - // Supply the copy and move, so you might use this as a class member too - Maybe(const Maybe &that) - { - if (that.get()) - create(*that); - } - - Maybe& operator= (const Maybe &that) - { - if (this != &that) { - if (that.get()) - create(*that); - else - reset(); - } - return *this; - } - - Maybe(Maybe &&that) - { - if (that.get()) - create(::std::move(*that)); - } - - Maybe& operator= (Maybe &&that) - { - if (this != &that) { - if (that.get()) - create(::std::move(*that)); - else - reset(); - } - return *this; - } - - // Make an object in the buffer, passing constructor arguments, - // but destroying any previous object first - // Note that if constructor throws, we remain in a consistent - // NULL state -- giving exception safety but only weakly - // (previous value was lost if present) - template - void create(Args... args) - { - // Lose any old value - reset(); - // Create new value - pp = safenew(address()) X( std::forward(args)... ); - } - - // Destroy any object that was built in it - ~Maybe() - { - reset(); - } - - // Pointer-like operators - - // Dereference, with the usual bad consequences if NULL - X &operator* () const - { - return *pp; - } - - X *operator-> () const - { - return pp; - } - - X* get() const - { - return pp; - } - - void reset() - { - if (pp) - pp->~X(), pp = nullptr; - } - - // So you can say if(ptr) - explicit operator bool() const - { - return pp != nullptr; - } - -private: - X* address() - { - return reinterpret_cast(&storage); - } - - // Data - typename ::std::aligned_storage< - sizeof(X) - // , alignof(X) // Not here yet in all compilers - >::type storage{}; - X* pp{ nullptr }; -}; - #endif // __AUDACITY_H__ diff --git a/src/AudacityHeaders.h b/src/AudacityHeaders.h index f91b5f6eb..33cc231d3 100644 --- a/src/AudacityHeaders.h +++ b/src/AudacityHeaders.h @@ -85,6 +85,7 @@ #ifdef _DEBUG #define _CRTDBG_MAP_ALLOC #include +#undef new #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) #define new DEBUG_NEW #endif diff --git a/src/BlockFile.cpp b/src/BlockFile.cpp index f4507c376..ad0bccd49 100644 --- a/src/BlockFile.cpp +++ b/src/BlockFile.cpp @@ -54,6 +54,7 @@ out. #include #include "Internat.h" +#include "MemoryX.h" // msmeyer: Define this to add debug output via printf() //#define DEBUG_BLOCKFILE diff --git a/src/DirManager.cpp b/src/DirManager.cpp index 7c71d2cc8..d54055db9 100644 --- a/src/DirManager.cpp +++ b/src/DirManager.cpp @@ -63,6 +63,7 @@ #include "Audacity.h" #include "DirManager.h" +#include "MemoryX.h" #include // to use time() for srand() diff --git a/src/FreqWindow.h b/src/FreqWindow.h index cdd05eb24..674f4f51f 100644 --- a/src/FreqWindow.h +++ b/src/FreqWindow.h @@ -11,7 +11,7 @@ #ifndef __AUDACITY_FREQ_WINDOW__ #define __AUDACITY_FREQ_WINDOW__ -#include +#include "MemoryX.h" #include #include #include diff --git a/src/Makefile.am b/src/Makefile.am index 38968a4b8..ae22f5ba8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -163,6 +163,7 @@ audacity_SOURCES = \ MacroMagic.h \ Matrix.cpp \ Matrix.h \ + MemoryX.h \ Menus.cpp \ Menus.h \ Mix.cpp \ diff --git a/src/MemoryX.h b/src/MemoryX.h new file mode 100644 index 000000000..ae068fcce --- /dev/null +++ b/src/MemoryX.h @@ -0,0 +1,191 @@ +#ifndef __AUDACITY_MEMORY_X_H__ +#define __AUDACITY_MEMORY_X_H__ + +// C++ standard header with a few extensions +#include + +#if !(defined(__WXMSW__) || defined(__WXMAC__)) +/* replicate the very useful C++14 make_unique for those build environments +that don't implement it yet. +typical useage: +auto p = std::make_unique(ctorArg1, ctorArg2, ... ctorArgN); +p->DoSomething(); +auto q = std::make_unique(count); +q[0].DoSomethingElse(); + +The first hides naked NEW and DELETE from the source code. +The second hides NEW[] and DELETE[]. Both of course ensure destruction if +you don't use something like std::move(p) or q.release(). Both expressions require +that you identify the type only once, which is brief and less error prone. + +(Whereas this omission of [] might invite a runtime error: +std::unique_ptr q { new Myclass[count] }; ) + +Some C++11 tricks needed here are (1) variadic argument lists and +(2) making the compile-time dispatch work correctly. You can't have +a partially specialized template function, but you get the effect of that +by other metaprogramming means. +*/ + +namespace std { + // For overloading resolution + template struct __make_unique_result { + using scalar_case = unique_ptr; + }; + + // Partial specialization of the struct for array case + template struct __make_unique_result { + using array_case = unique_ptr; + using element = X; + }; + + // Now the scalar version of unique_ptr + template inline + typename __make_unique_result::scalar_case + make_unique(Args&&... args) + { + return typename __make_unique_result::scalar_case + { safenew X(forward(args)...) }; + } + + // Now the array version of unique_ptr + // The compile-time dispatch trick is that the non-existence + // of the scalar_case type makes the above overload + // unavailable when the template parameter is explicit + template inline + typename __make_unique_result::array_case + make_unique(size_t count) + { + return typename __make_unique_result::array_case + { safenew typename __make_unique_result::element[count] }; + } +} +#endif + +/* +* template class Maybe +* Can be used for monomorphic objects that are stack-allocable, but only conditionally constructed. +* You might also use it as a member. +* Initialize with create(), then use like a smart pointer, +* with *, ->, get(), reset(), or in if() +*/ + +// Placement-new is used below, and that does not cooperate with the DEBUG_NEW for Visual Studio +#undef new + +template +class Maybe { +public: + + // Construct as NULL + Maybe() {} + + // Supply the copy and move, so you might use this as a class member too + Maybe(const Maybe &that) + { + if (that.get()) + create(*that); + } + + Maybe& operator= (const Maybe &that) + { + if (this != &that) { + if (that.get()) + create(*that); + else + reset(); + } + return *this; + } + + Maybe(Maybe &&that) + { + if (that.get()) + create(::std::move(*that)); + } + + Maybe& operator= (Maybe &&that) + { + if (this != &that) { + if (that.get()) + create(::std::move(*that)); + else + reset(); + } + return *this; + } + + // Make an object in the buffer, passing constructor arguments, + // but destroying any previous object first + // Note that if constructor throws, we remain in a consistent + // NULL state -- giving exception safety but only weakly + // (previous value was lost if present) + template + void create(Args... args) + { + // Lose any old value + reset(); + // Create new value + pp = safenew(address()) X(std::forward(args)...); + } + + // Destroy any object that was built in it + ~Maybe() + { + reset(); + } + + // Pointer-like operators + + // Dereference, with the usual bad consequences if NULL + X &operator* () const + { + return *pp; + } + + X *operator-> () const + { + return pp; + } + + X* get() const + { + return pp; + } + + void reset() + { + if (pp) + pp->~X(), pp = nullptr; + } + + // So you can say if(ptr) + explicit operator bool() const + { + return pp != nullptr; + } + +private: + X* address() + { + return reinterpret_cast(&storage); + } + + // Data + typename ::std::aligned_storage< + sizeof(X) + // , alignof(X) // Not here yet in all compilers + >::type storage{}; + X* pp{ nullptr }; +}; + +// Restore definition of debug new +#ifdef _DEBUG +#ifdef _MSC_VER +#undef THIS_FILE +static char*THIS_FILE = __FILE__; +#define new new(_NORMAL_BLOCK, THIS_FILE, __LINE__) +#endif +#endif + +#endif // __AUDACITY_MEMORY_X_H__ diff --git a/src/ShuttleGui.cpp b/src/ShuttleGui.cpp index ed403bf1c..aaf12d59a 100644 --- a/src/ShuttleGui.cpp +++ b/src/ShuttleGui.cpp @@ -94,8 +94,9 @@ for registering for changes. #include "Audacity.h" +#include "ShuttleGui.h" -#include +#include "MemoryX.h" #include #include #include @@ -104,7 +105,6 @@ for registering for changes. #include #include "Internat.h" #include "Experimental.h" -#include "ShuttleGui.h" #include "Shuttle.h" #include "WrappedType.h" diff --git a/src/ShuttleGui.h b/src/ShuttleGui.h index 931e64937..cb6f240a3 100644 --- a/src/ShuttleGui.h +++ b/src/ShuttleGui.h @@ -16,6 +16,7 @@ #include "Audacity.h" +#include "MemoryX.h" #include #include #include diff --git a/src/Tags.cpp b/src/Tags.cpp index 97c8f4ee6..84fbd0231 100644 --- a/src/Tags.cpp +++ b/src/Tags.cpp @@ -30,6 +30,9 @@ *//*******************************************************************/ +#include "Audacity.h" +#include "Tags.h" + // For compilers that support precompilation, includes "wx/wx.h". #include @@ -38,9 +41,6 @@ #include #endif -#include "Tags.h" - -#include "Audacity.h" #include "FileDialog.h" #include "FileNames.h" #include "Internat.h" diff --git a/src/Tags.h b/src/Tags.h index 65f594e5e..642988e7c 100644 --- a/src/Tags.h +++ b/src/Tags.h @@ -33,6 +33,7 @@ #include "widgets/Grid.h" #include "xml/XMLTagHandler.h" +#include "MemoryX.h" #include #include #include diff --git a/src/TrackPanel.h b/src/TrackPanel.h index bdfb25883..d4f13fea5 100644 --- a/src/TrackPanel.h +++ b/src/TrackPanel.h @@ -11,7 +11,7 @@ #ifndef __AUDACITY_TRACK_PANEL__ #define __AUDACITY_TRACK_PANEL__ -#include +#include "MemoryX.h" #include #include diff --git a/src/UndoManager.h b/src/UndoManager.h index 6c0226653..8cfeef0a2 100644 --- a/src/UndoManager.h +++ b/src/UndoManager.h @@ -48,7 +48,7 @@ #ifndef __AUDACITY_UNDOMANAGER__ #define __AUDACITY_UNDOMANAGER__ -#include +#include "MemoryX.h" #include #include #include "ondemand/ODTaskThread.h" diff --git a/src/WaveClip.cpp b/src/WaveClip.cpp index 964de70bb..8cf32df12 100644 --- a/src/WaveClip.cpp +++ b/src/WaveClip.cpp @@ -22,7 +22,7 @@ #include "WaveClip.h" #include -#include +#include "MemoryX.h" #include #include #include diff --git a/src/WaveTrack.cpp b/src/WaveTrack.cpp index 134b36ba7..bc83ad940 100644 --- a/src/WaveTrack.cpp +++ b/src/WaveTrack.cpp @@ -35,7 +35,7 @@ Track classes. #include #include #include -#include +#include "MemoryX.h" #include "float_cast.h" diff --git a/src/blockfile/LegacyBlockFile.cpp b/src/blockfile/LegacyBlockFile.cpp index 7e0f959c4..449afeeca 100644 --- a/src/blockfile/LegacyBlockFile.cpp +++ b/src/blockfile/LegacyBlockFile.cpp @@ -28,6 +28,7 @@ #include #include "LegacyBlockFile.h" +#include "../MemoryX.h" #include "../FileFormats.h" #include "../Internat.h" diff --git a/src/blockfile/PCMAliasBlockFile.cpp b/src/blockfile/PCMAliasBlockFile.cpp index 0559e8ef6..0892fc2ea 100644 --- a/src/blockfile/PCMAliasBlockFile.cpp +++ b/src/blockfile/PCMAliasBlockFile.cpp @@ -18,6 +18,7 @@ #include "PCMAliasBlockFile.h" #include "../FileFormats.h" #include "../Internat.h" +#include "../MemoryX.h" #include "../ondemand/ODManager.h" #include "../AudioIO.h" diff --git a/src/blockfile/SimpleBlockFile.cpp b/src/blockfile/SimpleBlockFile.cpp index fd5ad5751..4c45557ad 100644 --- a/src/blockfile/SimpleBlockFile.cpp +++ b/src/blockfile/SimpleBlockFile.cpp @@ -70,6 +70,7 @@ to get its definition, rather than rolling our own. #include "sndfile.h" #include "../Internat.h" +#include "../MemoryX.h" static wxUint32 SwapUintEndianess(wxUint32 in) diff --git a/src/commands/CommandManager.h b/src/commands/CommandManager.h index 488063d00..ee74efff9 100644 --- a/src/commands/CommandManager.h +++ b/src/commands/CommandManager.h @@ -14,6 +14,7 @@ #include "../Experimental.h" +#include "MemoryX.h" #include #include #include diff --git a/src/effects/FindClipping.cpp b/src/effects/FindClipping.cpp index 047a8cc3a..5e2dee58f 100644 --- a/src/effects/FindClipping.cpp +++ b/src/effects/FindClipping.cpp @@ -32,6 +32,7 @@ #include "../LabelTrack.h" #include "../WaveTrack.h" +#include "../MemoryX.h" // Define keys, defaults, minimums, and maximums for the effect parameters // diff --git a/src/effects/Generator.cpp b/src/effects/Generator.cpp index d568606f1..b3ee5fa1a 100644 --- a/src/effects/Generator.cpp +++ b/src/effects/Generator.cpp @@ -22,7 +22,7 @@ #include "TimeWarper.h" -#include +#include "../MemoryX.h" bool Generator::Process() { diff --git a/src/effects/NoiseReduction.h b/src/effects/NoiseReduction.h index f5583a4a6..d0f4105f2 100644 --- a/src/effects/NoiseReduction.h +++ b/src/effects/NoiseReduction.h @@ -15,7 +15,7 @@ #include "Effect.h" -#include +#include "../MemoryX.h" #define NOISEREDUCTION_PLUGIN_SYMBOL XO("Noise Reduction") diff --git a/src/effects/VST/VSTEffect.cpp b/src/effects/VST/VSTEffect.cpp index 51c8fda17..8cc9d1e51 100644 --- a/src/effects/VST/VSTEffect.cpp +++ b/src/effects/VST/VSTEffect.cpp @@ -93,6 +93,7 @@ #include "audacity/ConfigInterface.h" #include "VSTEffect.h" +#include "../../MemoryX.h" // NOTE: To debug the subprocess, use wxLogDebug and, on Windows, Debugview // from TechNet (Sysinternals). diff --git a/src/import/Import.cpp b/src/import/Import.cpp index 46235bfb6..4cf2ce6e0 100644 --- a/src/import/Import.cpp +++ b/src/import/Import.cpp @@ -35,6 +35,10 @@ and ImportLOF.cpp. +#include "../Audacity.h" +#include "Import.h" +#include "ImportPlugin.h" + #include #include #include @@ -44,11 +48,8 @@ and ImportLOF.cpp. #include #include #include "../ShuttleGui.h" -#include "../Audacity.h" #include "../Project.h" -#include "Import.h" -#include "ImportPlugin.h" #include "ImportPCM.h" #include "ImportMP3.h" #include "ImportOGG.h" diff --git a/src/import/ImportPlugin.h b/src/import/ImportPlugin.h index 8b506baa0..97fa4c6c3 100644 --- a/src/import/ImportPlugin.h +++ b/src/import/ImportPlugin.h @@ -55,10 +55,12 @@ but little else. #ifndef __AUDACITY_IMPORTER__ #define __AUDACITY_IMPORTER__ +#include "../Audacity.h" #include #include #include #include +#include "../MemoryX.h" #include "../widgets/ProgressDialog.h" diff --git a/src/toolbars/SpectralSelectionBar.cpp b/src/toolbars/SpectralSelectionBar.cpp index b96915446..7dc674892 100644 --- a/src/toolbars/SpectralSelectionBar.cpp +++ b/src/toolbars/SpectralSelectionBar.cpp @@ -29,6 +29,7 @@ with changes in the SpectralSelectionBar. #include "../Audacity.h" #include +#include "../MemoryX.h" // For compilers that support precompilation, includes "wx/wx.h". #include diff --git a/src/widgets/AButton.h b/src/widgets/AButton.h index df9b64c76..bf06bd5ff 100644 --- a/src/widgets/AButton.h +++ b/src/widgets/AButton.h @@ -12,7 +12,7 @@ #ifndef __AUDACITY_BUTTON__ #define __AUDACITY_BUTTON__ -#include +#include "../MemoryX.h" #include #if wxUSE_ACCESSIBILITY diff --git a/src/widgets/ProgressDialog.cpp b/src/widgets/ProgressDialog.cpp index d6b4d5c32..73b2f1f79 100644 --- a/src/widgets/ProgressDialog.cpp +++ b/src/widgets/ProgressDialog.cpp @@ -28,6 +28,7 @@ #include "../Audacity.h" +#include "../MemoryX.h" #include #include #include diff --git a/src/xml/XMLTagHandler.cpp b/src/xml/XMLTagHandler.cpp index be053e280..8ee4a7801 100644 --- a/src/xml/XMLTagHandler.cpp +++ b/src/xml/XMLTagHandler.cpp @@ -21,9 +21,10 @@ *//*******************************************************************/ +#include "../Audacity.h" #include "XMLTagHandler.h" -#include "../Audacity.h" +#include "../MemoryX.h" #include "../Internat.h" #ifdef _WIN32 diff --git a/win/Projects/Audacity/Audacity.vcxproj b/win/Projects/Audacity/Audacity.vcxproj index 6c0fa3803..1d29babb4 100755 --- a/win/Projects/Audacity/Audacity.vcxproj +++ b/win/Projects/Audacity/Audacity.vcxproj @@ -419,6 +419,7 @@ + diff --git a/win/Projects/Audacity/Audacity.vcxproj.filters b/win/Projects/Audacity/Audacity.vcxproj.filters index dc121908a..a9fc35947 100755 --- a/win/Projects/Audacity/Audacity.vcxproj.filters +++ b/win/Projects/Audacity/Audacity.vcxproj.filters @@ -1714,6 +1714,9 @@ src + + src +