mirror of https://github.com/stella-emu/stella.git
Get rid of mutexes on all critical code paths.
This commit is contained in:
parent
341dbb2b6f
commit
f03435f1a9
|
@ -17,7 +17,6 @@
|
||||||
|
|
||||||
#include "AudioQueue.hxx"
|
#include "AudioQueue.hxx"
|
||||||
|
|
||||||
using std::mutex;
|
|
||||||
using std::lock_guard;
|
using std::lock_guard;
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -54,7 +53,7 @@ uInt32 AudioQueue::capacity() const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
uInt32 AudioQueue::size() const
|
uInt32 AudioQueue::size() const
|
||||||
{
|
{
|
||||||
const lock_guard<Lock> guard(myLock);
|
const lock_guard<MutexOrSpinlock> guard(myLock);
|
||||||
|
|
||||||
return mySize;
|
return mySize;
|
||||||
}
|
}
|
||||||
|
@ -74,7 +73,7 @@ uInt32 AudioQueue::fragmentSize() const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Int16* AudioQueue::enqueue(Int16* fragment)
|
Int16* AudioQueue::enqueue(Int16* fragment)
|
||||||
{
|
{
|
||||||
const lock_guard<Lock> guard(myLock);
|
const lock_guard<MutexOrSpinlock> guard(myLock);
|
||||||
|
|
||||||
Int16* newFragment = nullptr;
|
Int16* newFragment = nullptr;
|
||||||
|
|
||||||
|
@ -105,7 +104,7 @@ Int16* AudioQueue::enqueue(Int16* fragment)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Int16* AudioQueue::dequeue(Int16* fragment)
|
Int16* AudioQueue::dequeue(Int16* fragment)
|
||||||
{
|
{
|
||||||
const lock_guard<Lock> guard(myLock);
|
const lock_guard<MutexOrSpinlock> guard(myLock);
|
||||||
|
|
||||||
if (mySize == 0) return nullptr;
|
if (mySize == 0) return nullptr;
|
||||||
|
|
||||||
|
@ -128,7 +127,7 @@ Int16* AudioQueue::dequeue(Int16* fragment)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void AudioQueue::closeSink(Int16* fragment)
|
void AudioQueue::closeSink(Int16* fragment)
|
||||||
{
|
{
|
||||||
const lock_guard<Lock> guard(myLock);
|
const lock_guard<MutexOrSpinlock> guard(myLock);
|
||||||
|
|
||||||
if (myFirstFragmentForDequeue && fragment)
|
if (myFirstFragmentForDequeue && fragment)
|
||||||
throw runtime_error("attempt to return unknown buffer on closeSink");
|
throw runtime_error("attempt to return unknown buffer on closeSink");
|
||||||
|
|
|
@ -18,9 +18,8 @@
|
||||||
#ifndef AUDIO_QUEUE_HXX
|
#ifndef AUDIO_QUEUE_HXX
|
||||||
#define AUDIO_QUEUE_HXX
|
#define AUDIO_QUEUE_HXX
|
||||||
|
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
#include "Lock.hxx"
|
||||||
#include "StaggeredLogger.hxx"
|
#include "StaggeredLogger.hxx"
|
||||||
|
|
||||||
#ifdef RTSTELLA
|
#ifdef RTSTELLA
|
||||||
|
@ -40,11 +39,6 @@
|
||||||
*/
|
*/
|
||||||
class AudioQueue
|
class AudioQueue
|
||||||
{
|
{
|
||||||
#ifdef RTSTELLA
|
|
||||||
using Lock = Spinlock;
|
|
||||||
#else
|
|
||||||
using Lock = std::Mutex;
|
|
||||||
#endif
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -129,7 +123,7 @@ class AudioQueue
|
||||||
uInt32 myNextFragment{0};
|
uInt32 myNextFragment{0};
|
||||||
|
|
||||||
// We need a mutex for thread safety.
|
// We need a mutex for thread safety.
|
||||||
mutable Lock myLock;
|
mutable MutexOrSpinlock myLock;
|
||||||
|
|
||||||
|
|
||||||
// The first (empty) enqueue call returns this fragment.
|
// The first (empty) enqueue call returns this fragment.
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// SSSS tt lll lll
|
||||||
|
// SS SS tt ll ll
|
||||||
|
// SS tttttt eeee ll ll aaaa
|
||||||
|
// SSSS tt ee ee ll ll aa
|
||||||
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||||
|
// SS SS tt ee ll ll aa aa
|
||||||
|
// SSSS ttt eeeee llll llll aaaaa
|
||||||
|
//
|
||||||
|
// Copyright (c) 1995-2023 by Bradford W. Mott, Stephen Anthony
|
||||||
|
// and the Stella Team
|
||||||
|
//
|
||||||
|
// See the file "License.txt" for information on usage and redistribution of
|
||||||
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
#ifdef RTSTELLA
|
||||||
|
#include "Spinlock.hxx"
|
||||||
|
|
||||||
|
using MutexOrSpinlock = Spinlock;
|
||||||
|
#else
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
using MutexOrSpinlock = std::mutex;
|
||||||
|
#endif
|
|
@ -16,6 +16,7 @@
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include "Logger.hxx"
|
#include "Logger.hxx"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Logger& Logger::instance()
|
Logger& Logger::instance()
|
||||||
|
@ -51,7 +52,7 @@ void Logger::debug(string_view message)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Logger::logMessage(string_view message, Level level)
|
void Logger::logMessage(string_view message, Level level)
|
||||||
{
|
{
|
||||||
const std::lock_guard<std::mutex> lock(mutex);
|
const std::lock_guard<MutexOrSpinlock> lock(mutex);
|
||||||
|
|
||||||
if(level == Logger::Level::ERR)
|
if(level == Logger::Level::ERR)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
#define LOGGER_HXX
|
#define LOGGER_HXX
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <mutex>
|
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
#include "Lock.hxx"
|
||||||
|
|
||||||
class Logger {
|
class Logger {
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ class Logger {
|
||||||
// The list of log messages
|
// The list of log messages
|
||||||
string myLogMessages;
|
string myLogMessages;
|
||||||
|
|
||||||
std::mutex mutex;
|
MutexOrSpinlock mutex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void logMessage(string_view message, Level level);
|
void logMessage(string_view message, Level level);
|
||||||
|
|
|
@ -45,6 +45,7 @@ StaggeredLogger::StaggeredLogger(string_view message, Logger::Level level)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
StaggeredLogger::~StaggeredLogger()
|
StaggeredLogger::~StaggeredLogger()
|
||||||
{
|
{
|
||||||
|
#ifndef RTSTELLA
|
||||||
myTimer->clear(myTimerId);
|
myTimer->clear(myTimerId);
|
||||||
|
|
||||||
// make sure that the worker thread joins before continuing with the destruction
|
// make sure that the worker thread joins before continuing with the destruction
|
||||||
|
@ -52,16 +53,23 @@ StaggeredLogger::~StaggeredLogger()
|
||||||
|
|
||||||
// the worker thread has joined and there will be no more reentrant calls ->
|
// the worker thread has joined and there will be no more reentrant calls ->
|
||||||
// continue with destruction
|
// continue with destruction
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void StaggeredLogger::log()
|
void StaggeredLogger::log()
|
||||||
{
|
{
|
||||||
|
#ifdef RTSTELLA
|
||||||
|
Logger::log(myMessage, myLevel);
|
||||||
|
#else
|
||||||
const std::lock_guard<std::mutex> lock(myMutex);
|
const std::lock_guard<std::mutex> lock(myMutex);
|
||||||
|
|
||||||
_log();
|
_log();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef RTSTELLA
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void StaggeredLogger::_log()
|
void StaggeredLogger::_log()
|
||||||
{
|
{
|
||||||
|
@ -143,3 +151,5 @@ void StaggeredLogger::onTimerExpired(uInt32 timerCallbackId)
|
||||||
|
|
||||||
myLastIntervalEndTimestamp = high_resolution_clock::now();
|
myLastIntervalEndTimestamp = high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -44,7 +44,7 @@ class StaggeredLogger
|
||||||
void log();
|
void log();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
#ifndef RTSTELLA
|
||||||
void _log();
|
void _log();
|
||||||
|
|
||||||
void onTimerExpired(uInt32 timerCallbackId);
|
void onTimerExpired(uInt32 timerCallbackId);
|
||||||
|
@ -56,10 +56,13 @@ class StaggeredLogger
|
||||||
void decreaseInterval();
|
void decreaseInterval();
|
||||||
|
|
||||||
void logLine();
|
void logLine();
|
||||||
|
#endif
|
||||||
|
|
||||||
string myMessage;
|
string myMessage;
|
||||||
Logger::Level myLevel;
|
Logger::Level myLevel;
|
||||||
|
|
||||||
|
#ifndef RTSTELLA
|
||||||
|
|
||||||
uInt32 myCurrentEventCount{0};
|
uInt32 myCurrentEventCount{0};
|
||||||
bool myIsCurrentlyCollecting{false};
|
bool myIsCurrentlyCollecting{false};
|
||||||
|
|
||||||
|
@ -83,7 +86,7 @@ class StaggeredLogger
|
||||||
// returns. This id is unique per timer and is used to return from the callback
|
// returns. This id is unique per timer and is used to return from the callback
|
||||||
// early in case the time is stale.
|
// early in case the time is stale.
|
||||||
uInt32 myTimerCallbackId{0};
|
uInt32 myTimerCallbackId{0};
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
StaggeredLogger(const StaggeredLogger&) = delete;
|
StaggeredLogger(const StaggeredLogger&) = delete;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
|
#include "Lock.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@author Stephen Anthony, Christian Speckner, Thomas Jentzsch
|
@author Stephen Anthony, Christian Speckner, Thomas Jentzsch
|
||||||
|
@ -206,7 +207,7 @@ class Event
|
||||||
Get the value associated with the event of the specified type.
|
Get the value associated with the event of the specified type.
|
||||||
*/
|
*/
|
||||||
Int32 get(Type type) const {
|
Int32 get(Type type) const {
|
||||||
std::lock_guard<std::mutex> lock(myMutex);
|
std::lock_guard<MutexOrSpinlock> lock(myMutex);
|
||||||
|
|
||||||
return myValues[type];
|
return myValues[type];
|
||||||
}
|
}
|
||||||
|
@ -215,7 +216,7 @@ class Event
|
||||||
Set the value associated with the event of the specified type.
|
Set the value associated with the event of the specified type.
|
||||||
*/
|
*/
|
||||||
void set(Type type, Int32 value) {
|
void set(Type type, Int32 value) {
|
||||||
std::lock_guard<std::mutex> lock(myMutex);
|
std::lock_guard<MutexOrSpinlock> lock(myMutex);
|
||||||
|
|
||||||
myValues[type] = value;
|
myValues[type] = value;
|
||||||
}
|
}
|
||||||
|
@ -225,7 +226,7 @@ class Event
|
||||||
*/
|
*/
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(myMutex);
|
std::lock_guard<MutexOrSpinlock> lock(myMutex);
|
||||||
|
|
||||||
myValues.fill(Event::NoType);
|
myValues.fill(Event::NoType);
|
||||||
}
|
}
|
||||||
|
@ -253,7 +254,7 @@ class Event
|
||||||
// Array of values associated with each event type
|
// Array of values associated with each event type
|
||||||
std::array<Int32, LastType> myValues;
|
std::array<Int32, LastType> myValues;
|
||||||
|
|
||||||
mutable std::mutex myMutex;
|
mutable MutexOrSpinlock myMutex;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
|
|
|
@ -151,11 +151,14 @@ void EventHandler::reset(EventHandlerState state)
|
||||||
#endif
|
#endif
|
||||||
myFryingFlag = false;
|
myFryingFlag = false;
|
||||||
|
|
||||||
|
#ifndef RTSTELLA
|
||||||
// Reset events almost immediately after starting emulation mode
|
// Reset events almost immediately after starting emulation mode
|
||||||
// We wait a little while (0.5s), since 'hold' events may be present,
|
// We wait a little while (0.5s), since 'hold' events may be present,
|
||||||
// and we want time for the ROM to process them
|
// and we want time for the ROM to process them
|
||||||
if(state == EventHandlerState::EMULATION)
|
if(state == EventHandlerState::EMULATION)
|
||||||
myOSystem.timer().setTimeout([&ev = myEvent]() { ev.clear(); }, 500);
|
myOSystem.timer().setTimeout([&ev = myEvent]() { ev.clear(); }, 500);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Toggle 7800 mode
|
// Toggle 7800 mode
|
||||||
set7800Mode();
|
set7800Mode();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue