diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0808ea7de..426229e9f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -191,6 +191,8 @@ list( APPEND SOURCES Prefs.h Printing.cpp Printing.h + Profiler.cpp + Profiler.h Project.cpp Project.h ProjectAudioIO.cpp diff --git a/src/FileFormats.cpp b/src/FileFormats.cpp index 156079444..7f086caf5 100644 --- a/src/FileFormats.cpp +++ b/src/FileFormats.cpp @@ -320,6 +320,8 @@ static OSType sf_header_mactype(int format) #endif // __WXMAC__ +//std::mutex libSndFileMutex; + int SFFileCloser::operator() (SNDFILE *sf) const { auto err = SFCall(sf_close, sf); diff --git a/src/FileFormats.h b/src/FileFormats.h index 0bdac41ac..4d7696079 100644 --- a/src/FileFormats.h +++ b/src/FileFormats.h @@ -15,6 +15,7 @@ #include "audacity/Types.h" +//#include #include "MemoryX.h" #include "sndfile.h" @@ -105,9 +106,16 @@ extern FileExtensions sf_get_all_extensions(); wxString sf_normalize_name(const char *name); + +// This function wrapper uses a mutex to serialize calls to the SndFile library. +// PRL: Keeping this in a comment, but with Unitary, the only remaining uses +// of libsndfile should be in import/export and so are on the main thread only +//extern std::mutex libSndFileMutex; + template inline R SFCall(F fun, Args&&... args) { + //std::lock_guard guard{ libSndFileMutex }; return fun(std::forward(args)...); } diff --git a/src/Profiler.cpp b/src/Profiler.cpp index 6c106d6b6..76c1b3c92 100644 --- a/src/Profiler.cpp +++ b/src/Profiler.cpp @@ -63,20 +63,18 @@ Profiler::~Profiler() ///start the task timer. void Profiler::Begin(const char* fileName, int lineNum, const char* taskDescription) { - mTasksMutex.Lock(); + std::lock_guard guard{ mTasksMutex }; GetOrCreateTaskProfile(fileName,lineNum)->Begin(fileName,lineNum,taskDescription); - mTasksMutex.Unlock(); } ///end the task timer. void Profiler::End(const char* fileName, int lineNum, const char* taskDescription) { - mTasksMutex.Lock(); + std::lock_guard guard{ mTasksMutex }; TaskProfile* tp; tp=GetTaskProfileByDescription(taskDescription); if(tp) tp->End(fileName,lineNum,taskDescription); - mTasksMutex.Unlock(); } ///Gets the singleton instance diff --git a/src/Profiler.h b/src/Profiler.h index 149820396..698cbbb5b 100644 --- a/src/Profiler.h +++ b/src/Profiler.h @@ -26,8 +26,10 @@ but it will probably work fine if you use it on a high level. #ifndef __AUDACITY_PROFILER__ #define __AUDACITY_PROFILER__ +#include #include #include +#include "MemoryX.h" #define BEGIN_TASK_PROFILING(TASK_DESCRIPTION) Profiler::Instance()->Begin(__FILE__,__LINE__,TASK_DESCRIPTION) @@ -59,6 +61,8 @@ class Profiler //List of current Task to do. std::vector> mTasks; + //mutex for above variable + std::mutex mTasksMutex; }; diff --git a/src/Project.cpp b/src/Project.cpp index 4e624fa4a..9e08a5329 100644 --- a/src/Project.cpp +++ b/src/Project.cpp @@ -47,6 +47,7 @@ auto AllProjects::rend() const -> const_reverse_iterator auto AllProjects::Remove( AudacityProject &project ) -> value_type { + std::lock_guard guard{ Mutex() }; auto start = begin(), finish = end(), iter = std::find_if( start, finish, [&]( const value_type &ptr ){ return ptr.get() == &project; } @@ -60,6 +61,7 @@ auto AllProjects::Remove( AudacityProject &project ) -> value_type void AllProjects::Add( const value_type &pProject ) { + std::lock_guard guard{ Mutex() }; gAudacityProjects.push_back( pProject ); } @@ -85,6 +87,12 @@ bool AllProjects::Close( bool force ) return true; } +std::mutex &AllProjects::Mutex() +{ + static std::mutex theMutex; + return theMutex; +} + int AudacityProject::mProjectCounter=0;// global counter. /* Define Global Variables */ diff --git a/src/Project.h b/src/Project.h index 047858fa2..a386aba39 100644 --- a/src/Project.h +++ b/src/Project.h @@ -16,6 +16,7 @@ #include "ClientData.h" // to inherit #include +#include #include // member variable #include // MSVC wants this @@ -63,6 +64,10 @@ public: // This invalidates iterators void Add( const value_type &pProject ); + /// In case you must iterate in a non-main thread, use this to prevent + /// changes in the set of open projects + static std::mutex &Mutex(); + // Return true if all projects do close (always so if force == true) // But if return is false, that means the user cancelled close of at least // one un-saved project.