Commit 77f83424 authored by Hugo Beauzée-Luyssen's avatar Hugo Beauzée-Luyssen

Add a std::mutex compatibility layer

Because mingw-w64 (at least) doesn't have C++11 mutexes
parent 5533610a
......@@ -146,6 +146,7 @@ noinst_HEADERS = \
src/utils/ToString.h \
src/VideoTrack.h \
src/compat/Thread.h \
src/compat/Mutex.h \
$(NULL)
......
......@@ -228,6 +228,15 @@ AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include <thread>
],[ AC_MSG_RESULT([no])])
AC_LANG_POP([C++])
AC_LANG_PUSH([C++])
AC_MSG_CHECKING([c++11 std::mutex support])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([#include <mutex>
int main() { std::mutex m; }])], [
AC_MSG_RESULT([ok])
AC_DEFINE(CXX11_MUTEX, 1, [Defined to 1 if C++11 std::mutex is supported])
],[ AC_MSG_RESULT([no])])
AC_LANG_POP([C++])
AC_LANG_PUSH([C++])
AC_MSG_CHECKING([c++11 thread_local support])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([thread_local int seaOtter = 0;
......
/*****************************************************************************
* Media Library
*****************************************************************************
* Copyright (C) 2015 Hugo Beauzée-Luyssen, Videolabs
*
* Authors: Hugo Beauzée-Luyssen<hugo@beauzee.fr>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#pragma once
// Include mutex unconditionnaly for lock_gard & unique_lock
#include <mutex>
#if CXX11_MUTEX
#include <mutex>
namespace medialibrary
{
namespace compat
{
using Mutex = std::mutex;
}
}
#else
#include <windows.h>
namespace medialibrary
{
namespace compat
{
class Mutex
{
public:
using native_handle_type = CRITICAL_SECTION*;
Mutex()
{
InitializeCriticalSection( &m_lock );
}
~Mutex()
{
DeleteCriticalSection( &m_lock );
}
void lock()
{
EnterCriticalSection( &m_lock );
}
bool try_lock()
{
return TryEnterCriticalSection( &m_lock );
}
void unlock()
{
LeaveCriticalSection( &m_lock );
}
native_handle_type native_handle()
{
return &m_lock;
}
private:
CRITICAL_SECTION m_lock;
};
}
}
#endif
......@@ -23,10 +23,10 @@
#pragma once
#include <memory>
#include <mutex>
#include <unordered_map>
#include <vector>
#include "compat/Mutex.h"
#include "SqliteTools.h"
namespace medialibrary
......@@ -35,7 +35,7 @@ namespace medialibrary
template <typename IMPL, typename TABLEPOLICY>
class DatabaseHelpers
{
using Lock = std::lock_guard<std::mutex>;
using Lock = std::lock_guard<compat::Mutex>;
public:
template <typename... Args>
......@@ -123,7 +123,7 @@ class DatabaseHelpers
private:
static std::unordered_map<int64_t, std::shared_ptr<IMPL>> Store;
static std::mutex Mutex;
static compat::Mutex Mutex;
};
......@@ -132,6 +132,6 @@ std::unordered_map<int64_t, std::shared_ptr<IMPL>>
DatabaseHelpers<IMPL, TABLEPOLICY>::Store;
template <typename IMPL, typename TABLEPOLICY>
std::mutex DatabaseHelpers<IMPL, TABLEPOLICY>::Mutex;
compat::Mutex DatabaseHelpers<IMPL, TABLEPOLICY>::Mutex;
}
......@@ -49,7 +49,7 @@ SqliteConnection::~SqliteConnection()
SqliteConnection::Handle SqliteConnection::getConn()
{
std::unique_lock<std::mutex> lock( m_connMutex );
std::unique_lock<compat::Mutex> lock( m_connMutex );
sqlite3* dbConnection;
auto it = m_conns.find( compat::this_thread::get_id() );
if ( it == end( m_conns ) )
......
......@@ -27,11 +27,11 @@
#include <memory>
#include <sqlite3.h>
#include <condition_variable>
#include <mutex>
#include <unordered_map>
#include <string>
#include "utils/SWMRLock.h"
#include "compat/Mutex.h"
#include "compat/Thread.h"
namespace medialibrary
......@@ -74,7 +74,7 @@ private:
private:
using ConnPtr = std::unique_ptr<sqlite3, int(*)(sqlite3*)>;
const std::string m_dbPath;
std::mutex m_connMutex;
compat::Mutex m_connMutex;
std::unordered_map<compat::Thread::id, ConnPtr> m_conns;
utils::SWMRLock m_contextLock;
utils::ReadLocker m_readLock;
......
......@@ -34,7 +34,7 @@ namespace sqlite
std::unordered_map<SqliteConnection::Handle,
std::unordered_map<std::string, Statement::CachedStmtPtr>> Statement::StatementsCache;
std::mutex Statement::StatementsCacheLock;
compat::Mutex Statement::StatementsCacheLock;
}
}
......@@ -32,6 +32,7 @@
#include <unordered_map>
#include <vector>
#include <compat/Mutex.h>
#include "database/SqliteConnection.h"
#include "database/SqliteErrors.h"
#include "database/SqliteTraits.h"
......@@ -113,7 +114,7 @@ public:
, m_dbConn( dbConnection )
, m_bindIdx( 0 )
{
std::lock_guard<std::mutex> lock( StatementsCacheLock );
std::lock_guard<compat::Mutex> lock( StatementsCacheLock );
auto& connMap = StatementsCache[ dbConnection ];
auto it = connMap.find( req );
if ( it == end( connMap ) )
......@@ -164,7 +165,7 @@ public:
static void FlushStatementCache()
{
std::lock_guard<std::mutex> lock( StatementsCacheLock );
std::lock_guard<compat::Mutex> lock( StatementsCacheLock );
StatementsCache.clear();
}
......@@ -188,7 +189,7 @@ private:
StatementPtr m_stmt;
SqliteConnection::Handle m_dbConn;
unsigned int m_bindIdx;
static std::mutex StatementsCacheLock;
static compat::Mutex StatementsCacheLock;
static std::unordered_map<SqliteConnection::Handle,
std::unordered_map<std::string, CachedStmtPtr>> StatementsCache;
};
......
......@@ -54,7 +54,7 @@ void DiscovererWorker::stop()
if ( m_run.compare_exchange_strong( running, false ) )
{
{
std::unique_lock<std::mutex> lock( m_mutex );
std::unique_lock<compat::Mutex> lock( m_mutex );
while ( m_tasks.empty() == false )
m_tasks.pop();
}
......@@ -83,7 +83,7 @@ void DiscovererWorker::reload( const std::string& entryPoint )
void DiscovererWorker::enqueue( const std::string& entryPoint, bool reload )
{
std::unique_lock<std::mutex> lock( m_mutex );
std::unique_lock<compat::Mutex> lock( m_mutex );
m_tasks.emplace( entryPoint, reload );
if ( m_thread.get_id() == compat::Thread::id{} )
......@@ -103,7 +103,7 @@ void DiscovererWorker::run()
{
Task task;
{
std::unique_lock<std::mutex> lock( m_mutex );
std::unique_lock<compat::Mutex> lock( m_mutex );
if ( m_tasks.size() == 0 )
{
m_cond.wait( lock, [this]() { return m_tasks.size() > 0 || m_run == false; } );
......
......@@ -25,11 +25,11 @@
#include <atomic>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <queue>
#include <string>
#include <vector>
#include "compat/Mutex.h"
#include "compat/Thread.h"
#include "discoverer/IDiscoverer.h"
......@@ -64,7 +64,7 @@ private:
compat::Thread m_thread;
std::queue<Task> m_tasks;
std::mutex m_mutex;
compat::Mutex m_mutex;
std::condition_variable m_cond;
std::atomic_bool m_run;
std::vector<std::unique_ptr<IDiscoverer>> m_discoverers;
......
......@@ -53,7 +53,7 @@ FileSystemFactory::FileSystemFactory( DeviceListerPtr lister )
std::shared_ptr<fs::IDirectory> FileSystemFactory::createDirectory( const std::string& path )
{
std::lock_guard<std::mutex> lock( m_mutex );
std::lock_guard<compat::Mutex> lock( m_mutex );
const auto it = m_dirs.find( path );
if ( it != end( m_dirs ) )
return it->second;
......@@ -77,7 +77,7 @@ std::shared_ptr<fs::IDevice> FileSystemFactory::createDevice( const std::string&
void FileSystemFactory::refresh()
{
std::lock_guard<std::mutex> lock( m_mutex );
std::lock_guard<compat::Mutex> lock( m_mutex );
m_dirs.clear();
}
......
......@@ -22,10 +22,10 @@
#pragma once
#include "compat/Mutex.h"
#include "factory/IFileSystem.h"
#include "medialibrary/Types.h"
#include <mutex>
#include <string>
#include <unordered_map>
......@@ -44,7 +44,7 @@ namespace factory
private:
std::unordered_map<std::string, std::shared_ptr<fs::IDirectory>> m_dirs;
std::mutex m_mutex;
compat::Mutex m_mutex;
};
}
......
......@@ -57,12 +57,12 @@ parser::Task::Status VLCMetadataService::run( parser::Task& task )
auto vlcMedia = VLC::Media( m_instance, file->mrl(), VLC::Media::FromPath );
std::unique_lock<std::mutex> lock( m_mutex );
std::unique_lock<compat::Mutex> lock( m_mutex );
VLC::Media::ParsedStatus status;
bool done = false;
auto event = vlcMedia.eventManager().onParsedChanged( [this, &status, &done](VLC::Media::ParsedStatus s ) {
std::lock_guard<std::mutex> lock( m_mutex );
std::lock_guard<compat::Mutex> lock( m_mutex );
status = s;
done = true;
m_cond.notify_all();
......
......@@ -47,7 +47,7 @@ private:
private:
VLC::Instance m_instance;
std::mutex m_mutex;
compat::Mutex m_mutex;
std::condition_variable m_cond;
};
......
......@@ -121,7 +121,7 @@ parser::Task::Status VLCThumbnailer::startPlayback( VLC::MediaPlayer &mp )
em.onEncounteredError([this]() {
m_cond.notify_all();
});
std::unique_lock<std::mutex> lock( m_mutex );
std::unique_lock<compat::Mutex> lock( m_mutex );
mp.play();
bool success = m_cond.wait_for( lock, std::chrono::seconds( 3 ), [&mp]() {
auto s = mp.state();
......@@ -138,10 +138,10 @@ parser::Task::Status VLCThumbnailer::startPlayback( VLC::MediaPlayer &mp )
parser::Task::Status VLCThumbnailer::seekAhead( VLC::MediaPlayer& mp )
{
std::unique_lock<std::mutex> lock( m_mutex );
std::unique_lock<compat::Mutex> lock( m_mutex );
float pos = .0f;
auto event = mp.eventManager().onPositionChanged([this, &pos](float p) {
std::unique_lock<std::mutex> lock( m_mutex );
std::unique_lock<compat::Mutex> lock( m_mutex );
pos = p;
m_cond.notify_all();
});
......@@ -212,7 +212,7 @@ parser::Task::Status VLCThumbnailer::takeThumbnail( std::shared_ptr<Media> media
{
// lock, signal that we want a thumbnail, and wait.
{
std::unique_lock<std::mutex> lock( m_mutex );
std::unique_lock<compat::Mutex> lock( m_mutex );
m_thumbnailRequired = true;
bool success = m_cond.wait_for( lock, std::chrono::seconds( 3 ), [this]() {
// Keep waiting if the vmem thread hasn't restored m_thumbnailRequired to false
......
......@@ -57,7 +57,7 @@ private:
private:
VLC::Instance m_instance;
std::mutex m_mutex;
compat::Mutex m_mutex;
std::condition_variable m_cond;
std::unique_ptr<IImageCompressor> m_compressor;
// Per thumbnail variables
......
......@@ -49,13 +49,13 @@ void ParserService::start()
void ParserService::pause()
{
std::lock_guard<std::mutex> lock( m_lock );
std::lock_guard<compat::Mutex> lock( m_lock );
m_paused = true;
}
void ParserService::resume()
{
std::lock_guard<std::mutex> lock( m_lock );
std::lock_guard<compat::Mutex> lock( m_lock );
m_paused = false;
m_cond.notify_all();
}
......@@ -67,7 +67,7 @@ void ParserService::signalStop()
if ( t.joinable() )
{
{
std::lock_guard<std::mutex> lock( m_lock );
std::lock_guard<compat::Mutex> lock( m_lock );
m_cond.notify_all();
m_stopParser = true;
}
......@@ -86,7 +86,7 @@ void ParserService::stop()
void ParserService::parse( std::unique_ptr<parser::Task> t )
{
std::lock_guard<std::mutex> lock( m_lock );
std::lock_guard<compat::Mutex> lock( m_lock );
m_tasks.push( std::move( t ) );
m_cond.notify_all();
}
......@@ -126,7 +126,7 @@ void ParserService::mainloop()
{
std::unique_ptr<parser::Task> task;
{
std::unique_lock<std::mutex> lock( m_lock );
std::unique_lock<compat::Mutex> lock( m_lock );
if ( m_tasks.empty() == true || m_paused == true )
{
LOG_INFO( "Halting ParserService mainloop" );
......
......@@ -24,11 +24,11 @@
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <queue>
#include "Task.h"
#include "medialibrary/Types.h"
#include "compat/Mutex.h"
#include "compat/Thread.h"
namespace medialibrary
......@@ -86,7 +86,7 @@ private:
std::condition_variable m_cond;
std::queue<std::unique_ptr<parser::Task>> m_tasks;
std::vector<compat::Thread> m_threads;
std::mutex m_lock;
compat::Mutex m_lock;
};
}
......@@ -22,9 +22,10 @@
#pragma once
#include <mutex>
#include <cassert>
#include "compat/Mutex.h"
namespace medialibrary
{
......@@ -71,14 +72,14 @@ public:
return m_value;
}
std::unique_lock<std::mutex> lock()
std::unique_lock<compat::Mutex> lock()
{
return std::unique_lock<std::mutex>( m_lock );
return std::unique_lock<compat::Mutex>( m_lock );
}
private:
T m_value;
std::mutex m_lock;
compat::Mutex m_lock;
bool m_cached;
};
......
......@@ -134,7 +134,7 @@ void ModificationNotifier::run()
while ( m_stop == false )
{
{
std::unique_lock<std::mutex> lock( m_lock );
std::unique_lock<compat::Mutex> lock( m_lock );
if ( m_timeout == ZeroTimeout )
m_cond.wait( lock, [this, ZeroTimeout](){ return m_timeout != ZeroTimeout || m_stop == true; } );
m_cond.wait_until( lock, m_timeout, [this]() { return m_stop == true; });
......
......@@ -25,13 +25,13 @@
#include <atomic>
#include <condition_variable>
#include <functional>
#include <mutex>
#include <vector>
#include <chrono>
#include "medialibrary/Types.h"
#include "Types.h"
#include "compat/Thread.h"
#include "compat/Mutex.h"
namespace medialibrary
{
......@@ -87,7 +87,7 @@ private:
template <typename T>
void notifyCreation( std::shared_ptr<T> entity, Queue<T>& queue )
{
std::lock_guard<std::mutex> lock( m_lock );
std::lock_guard<compat::Mutex> lock( m_lock );
queue.added.push_back( std::move( entity ) );
updateTimeout( queue );
}
......@@ -95,7 +95,7 @@ private:
template <typename T>
void notifyModification( std::shared_ptr<T> entity, Queue<T>& queue )
{
std::lock_guard<std::mutex> lock( m_lock );
std::lock_guard<compat::Mutex> lock( m_lock );
queue.modified.push_back( std::move( entity ) );
updateTimeout( queue );
}
......@@ -103,7 +103,7 @@ private:
template <typename T>
void notifyRemoval( int64_t rowId, Queue<T>& queue )
{
std::lock_guard<std::mutex> lock( m_lock );
std::lock_guard<compat::Mutex> lock( m_lock );
queue.removed.push_back( rowId );
updateTimeout( m_media );
}
......@@ -153,7 +153,7 @@ private:
Queue<IAlbumTrack> m_tracks;
// Notifier thread
std::mutex m_lock;
compat::Mutex m_lock;
std::condition_variable m_cond;
compat::Thread m_notifierThread;
std::atomic_bool m_stop;
......
......@@ -23,7 +23,7 @@
#pragma once
#include <condition_variable>
#include <mutex>
#include "compat/Mutex.h"
#include <atomic>
namespace medialibrary
......@@ -48,7 +48,7 @@ public:
void lock_read()
{
std::unique_lock<std::mutex> lock( m_lock );
std::unique_lock<compat::Mutex> lock( m_lock );
++m_nbReaderWaiting;
m_writeDoneCond.wait( lock, [this](){
return m_writing == false;
......@@ -59,7 +59,7 @@ public:
void unlock_read()
{
std::unique_lock<std::mutex> lock( m_lock );
std::unique_lock<compat::Mutex> lock( m_lock );
--m_nbReader;
if ( m_nbReader == 0 && m_nbWriterWaiting > 0 )
m_writeDoneCond.notify_one();
......@@ -67,7 +67,7 @@ public:
void lock_write()
{
std::unique_lock<std::mutex> lock( m_lock );
std::unique_lock<compat::Mutex> lock( m_lock );
++m_nbWriterWaiting;
m_writeDoneCond.wait( lock, [this](){
return m_writing == false && m_nbReader == 0;
......@@ -78,7 +78,7 @@ public:
void unlock_write()
{
std::unique_lock<std::mutex> lock( m_lock );
std::unique_lock<compat::Mutex> lock( m_lock );
m_writing = false;
if ( m_nbReaderWaiting > 0 || m_nbWriterWaiting > 0 )
m_writeDoneCond.notify_one();
......@@ -86,7 +86,7 @@ public:
private:
std::condition_variable m_writeDoneCond;
std::mutex m_lock;
compat::Mutex m_lock;
unsigned int m_nbReader;
unsigned int m_nbReaderWaiting;
bool m_writing;
......
......@@ -49,7 +49,7 @@ public:
bool wait()
{
std::unique_lock<std::mutex> lock( m_mutex );
std::unique_lock<compat::Mutex> lock( m_mutex );
return m_cond.wait_for( lock, std::chrono::seconds( 5 ), [this]() {
return m_done.load();
} );
......@@ -76,7 +76,7 @@ private:
std::atomic_bool m_done;
std::atomic_bool m_waitingReload;
std::condition_variable m_cond;
std::mutex m_mutex;
compat::Mutex m_mutex;
};
}
......@@ -16,7 +16,7 @@ MockCallback::MockCallback()
bool MockCallback::waitForParsingComplete()
{
std::unique_lock<std::mutex> lock( m_parsingMutex, std::adopt_lock );
std::unique_lock<compat::Mutex> lock( m_parsingMutex, std::adopt_lock );
m_done = false;
m_discoveryCompleted = false;
// Wait for a while, generating snapshots can be heavy...
......@@ -29,7 +29,7 @@ void MockCallback::onDiscoveryCompleted(const std::string& entryPoint )
{
if ( entryPoint.empty() == true )
return;
std::lock_guard<std::mutex> lock( m_parsingMutex );
std::lock_guard<compat::Mutex> lock( m_parsingMutex );
m_discoveryCompleted = true;
}
......@@ -37,7 +37,7 @@ void MockCallback::onParsingStatsUpdated(uint32_t percent)
{
if ( percent == 100 )
{
std::lock_guard<std::mutex> lock( m_parsingMutex );
std::lock_guard<compat::Mutex> lock( m_parsingMutex );
if ( m_discoveryCompleted == false )
return;
m_done = true;
......
......@@ -49,7 +49,7 @@ private:
virtual void onParsingStatsUpdated(uint32_t percent) override;
std::condition_variable m_parsingCompleteVar;
std::mutex m_parsingMutex;
compat::Mutex m_parsingMutex;
bool m_done;
bool m_discoveryCompleted;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment