Browse Source

♻️ Implement std's Lockable for SDL mutex wrapper

Rather than rolling our own lock guard, implement the requirements for
using `std::lock_guard` et al and use that.
pull/2006/head
Gleb Mazovetskiy 5 years ago committed by Anders Jenbo
parent
commit
c79ec673f4
  1. 13
      Source/sound.cpp
  2. 9
      Source/storm/storm.cpp
  3. 9
      Source/utils/push_aulib_decoder.cpp
  4. 3
      Source/utils/push_aulib_decoder.h
  5. 43
      Source/utils/sdl_mutex.h

13
Source/sound.cpp

@ -8,6 +8,7 @@
#include <cstdint>
#include <list>
#include <memory>
#include <mutex>
#include <aulib.h>
#include <Aulib/DecoderDrwav.h>
@ -69,7 +70,7 @@ void CleanupMusic()
}
std::list<std::unique_ptr<SoundSample>> duplicateSounds;
SDLMutexUniquePtr duplicateSoundsMutex;
std::optional<SdlMutex> duplicateSoundsMutex;
SoundSample *DuplicateSound(const SoundSample &sound)
{
@ -79,13 +80,13 @@ SoundSample *DuplicateSound(const SoundSample &sound)
auto *result = duplicate.get();
decltype(duplicateSounds.begin()) it;
{
SDLMutexLockGuard lock(duplicateSoundsMutex.get());
const std::lock_guard<SdlMutex> lock(*duplicateSoundsMutex);
duplicateSounds.push_back(std::move(duplicate));
it = duplicateSounds.end();
--it;
}
result->SetFinishCallback([it]([[maybe_unused]] Aulib::Stream &stream) {
SDLMutexLockGuard lock(duplicateSoundsMutex.get());
const std::lock_guard<SdlMutex> lock(*duplicateSoundsMutex);
duplicateSounds.erase(it);
});
return result;
@ -129,7 +130,7 @@ static int CapVolume(int volume)
void ClearDuplicateSounds()
{
SDLMutexLockGuard lock(duplicateSoundsMutex.get());
const std::lock_guard<SdlMutex> lock(*duplicateSoundsMutex);
duplicateSounds.clear();
}
@ -214,7 +215,7 @@ void snd_init()
LogVerbose(LogCategory::Audio, "Aulib sampleRate={} channels={} frameSize={} format={:#x}",
Aulib::sampleRate(), Aulib::channelCount(), Aulib::frameSize(), Aulib::sampleFormat());
duplicateSoundsMutex = SDLMutexUniquePtr { SDL_CreateMutex() };
duplicateSoundsMutex.emplace();
gbSndInited = true;
}
@ -222,7 +223,7 @@ void snd_deinit()
{
if (gbSndInited) {
Aulib::quit();
duplicateSoundsMutex = nullptr;
duplicateSoundsMutex = std::nullopt;
}
gbSndInited = false;

9
Source/storm/storm.cpp

@ -4,6 +4,7 @@
#include <SDL_endian.h>
#include <cstddef>
#include <cstdint>
#include <mutex>
#include <string>
#include "Radon.hpp"
@ -34,19 +35,19 @@ namespace {
bool directFileAccess = false;
std::string *SBasePath = nullptr;
} // namespace
SdlMutex Mutex;
SDL_mutex *Mutex = SDL_CreateMutex();
} // namespace
bool SFileReadFileThreadSafe(HANDLE hFile, void *buffer, DWORD nNumberOfBytesToRead, DWORD *read, int *lpDistanceToMoveHigh)
{
SDLMutexLockGuard lock(Mutex);
const std::lock_guard<SdlMutex> lock(Mutex);
return SFileReadFile(hFile, buffer, nNumberOfBytesToRead, read, lpDistanceToMoveHigh);
}
bool SFileCloseFileThreadSafe(HANDLE hFile)
{
SDLMutexLockGuard lock(Mutex);
const std::lock_guard<SdlMutex> lock(Mutex);
return SFileCloseFile(hFile);
}

9
Source/utils/push_aulib_decoder.cpp

@ -3,6 +3,7 @@
#include <algorithm>
#include <cstring>
#include <limits>
#include <mutex>
#include <aulib.h>
@ -17,7 +18,7 @@ void PushAulibDecoder::PushSamples(const std::int16_t *data, unsigned size) noex
std::memcpy(item.data.get(), data, size * sizeof(data[0]));
item.len = size;
item.pos = item.data.get();
SDLMutexLockGuard lock(queue_mutex_.get());
const std::lock_guard<SdlMutex> lock(queue_mutex_);
queue_.push(std::move(item));
}
@ -31,13 +32,13 @@ void PushAulibDecoder::PushSamples(const std::uint8_t *data, unsigned size) noex
item.data[i] = static_cast<std::int16_t>((data[i] - Center) * Scale);
item.len = size;
item.pos = item.data.get();
SDLMutexLockGuard lock(queue_mutex_.get());
const std::lock_guard<SdlMutex> lock(queue_mutex_);
queue_.push(std::move(item));
}
void PushAulibDecoder::DiscardPendingSamples() noexcept
{
SDLMutexLockGuard lock(queue_mutex_.get());
const std::lock_guard<SdlMutex> lock(queue_mutex_);
queue_ = std::queue<AudioQueueItem>();
}
@ -75,7 +76,7 @@ int PushAulibDecoder::doDecoding(float buf[], int len, bool &callAgain)
unsigned remaining = len;
{
SDLMutexLockGuard lock(queue_mutex_.get());
const std::lock_guard<SdlMutex> lock(queue_mutex_);
AudioQueueItem *item;
while ((item = Next()) != nullptr) {
if (static_cast<unsigned>(remaining) <= item->len) {

3
Source/utils/push_aulib_decoder.h

@ -20,7 +20,6 @@ public:
PushAulibDecoder(int numChannels, int sampleRate)
: numChannels_(numChannels)
, sampleRate_(sampleRate)
, queue_mutex_(SDL_CreateMutex())
{
}
@ -61,7 +60,7 @@ private:
AudioQueueItem *Next();
std::queue<AudioQueueItem> queue_;
SDLMutexUniquePtr queue_mutex_;
SdlMutex queue_mutex_;
};
} // namespace devilution

43
Source/utils/sdl_mutex.h

@ -3,38 +3,47 @@
#include <memory>
#include <SDL_mutex.h>
#include <SDL_version.h>
namespace devilution {
/**
* @brief Deletes the SDL mutex using `SDL_DestroyMutex`.
/*
* RAII wrapper for SDL_mutex. Satisfies std's "Lockable" (SDL 2) or "BasicLockable" (SDL 1)
* requirements so it can be used with std::lock_guard and friends.
*/
struct SDLMutexDeleter {
void operator()(SDL_mutex *mutex) const
class SdlMutex final {
public:
SdlMutex()
: mutex_(SDL_CreateMutex())
{
SDL_DestroyMutex(mutex);
}
};
using SDLMutexUniquePtr = std::unique_ptr<SDL_mutex, SDLMutexDeleter>;
~SdlMutex()
{
SDL_DestroyMutex(mutex_);
}
struct SDLMutexLockGuard {
public:
explicit SDLMutexLockGuard(SDL_mutex *mutex)
: mutex_(mutex)
SdlMutex(const SdlMutex &) = delete;
SdlMutex(SdlMutex &&) = delete;
SdlMutex &operator=(const SdlMutex &) = delete;
SdlMutex &operator=(SdlMutex &&) = delete;
void lock() noexcept // NOLINT(readability-identifier-naming)
{
SDL_LockMutex(mutex_);
}
~SDLMutexLockGuard()
#if SDL_VERSION_ATLEAST(2, 0, 0)
bool try_lock() noexcept // NOLINT(readability-identifier-naming)
{
SDL_UnlockMutex(mutex_);
return SDL_TryLockMutex(mutex_) == 0;
}
#endif
SDLMutexLockGuard(const SDLMutexLockGuard &) = delete;
SDLMutexLockGuard(SDLMutexLockGuard &&) = delete;
SDLMutexLockGuard &operator=(const SDLMutexLockGuard &) = delete;
SDLMutexLockGuard &operator=(SDLMutexLockGuard &&) = delete;
void unlock() noexcept // NOLINT(readability-identifier-naming)
{
SDL_UnlockMutex(mutex_);
}
private:
SDL_mutex *mutex_;

Loading…
Cancel
Save