Use Common::Flag and Common::Event when possible

Replaces old and simple usages of std::atomic<bool> with Common::Flag
(which was introduced after the initial usage), so it's clear that
the variable is a flag and because Common::Flag is well tested.

This also replaces the ready logic in WiimoteReal with Common::Event
since it was basically just unnecessarily reimplementing Common::Event.
This commit is contained in:
Léo Lam 2016-08-05 16:04:39 +02:00
parent c6a0e543a5
commit dca22e08eb
19 changed files with 94 additions and 132 deletions

View File

@ -34,7 +34,7 @@ void AOSound::SoundLoop()
buf_size = format.bits / 8 * format.channels * format.rate;
while (m_run_thread.load())
while (m_run_thread.IsSet())
{
m_mixer->Mix(realtimeBuffer, numBytesToRender >> 2);
@ -49,7 +49,7 @@ void AOSound::SoundLoop()
bool AOSound::Start()
{
m_run_thread.store(true);
m_run_thread.Set();
memset(realtimeBuffer, 0, sizeof(realtimeBuffer));
thread = std::thread(&AOSound::SoundLoop, this);
@ -63,7 +63,7 @@ void AOSound::Update()
void AOSound::Stop()
{
m_run_thread.store(false);
m_run_thread.Clear();
soundSyncEvent.Set();
{

View File

@ -4,7 +4,6 @@
#pragma once
#include <atomic>
#include <mutex>
#include <thread>
@ -20,7 +19,7 @@ class AOSound final : public SoundStream
{
#if defined(HAVE_AO) && HAVE_AO
std::thread thread;
std::atomic<bool> m_run_thread;
Common::Flag m_run_thread;
std::mutex soundCriticalSection;
Common::Event soundSyncEvent;

View File

@ -25,7 +25,7 @@ static soundtouch::SoundTouch soundTouch;
//
bool OpenALStream::Start()
{
m_run_thread.store(true);
m_run_thread.Set();
bool bReturn = false;
ALDeviceList pDeviceList;
@ -75,7 +75,7 @@ bool OpenALStream::Start()
void OpenALStream::Stop()
{
m_run_thread.store(false);
m_run_thread.Clear();
// kick the thread if it's waiting
soundSyncEvent.Set();
@ -207,7 +207,7 @@ void OpenALStream::SoundLoop()
soundTouch.setSetting(SETTING_SEEKWINDOW_MS, 28);
soundTouch.setSetting(SETTING_OVERLAP_MS, 12);
while (m_run_thread.load())
while (m_run_thread.IsSet())
{
// num_samples_to_render in this update - depends on SystemTimers::AUDIO_DMA_PERIOD.
const u32 stereo_16_bit_size = 4;

View File

@ -4,7 +4,6 @@
#pragma once
#include <atomic>
#include <thread>
#include "AudioCommon/SoundStream.h"
@ -68,7 +67,7 @@ public:
static bool isValid() { return true; }
private:
std::thread thread;
std::atomic<bool> m_run_thread;
Common::Flag m_run_thread;
Common::Event soundSyncEvent;

View File

@ -27,7 +27,7 @@ bool PulseAudio::Start()
NOTICE_LOG(AUDIO, "PulseAudio backend using %d channels", m_channels);
m_run_thread = true;
m_run_thread.Set();
m_thread = std::thread(&PulseAudio::SoundLoop, this);
// Initialize DPL2 parameters
@ -38,7 +38,7 @@ bool PulseAudio::Start()
void PulseAudio::Stop()
{
m_run_thread = false;
m_run_thread.Clear();
m_thread.join();
}
@ -54,7 +54,7 @@ void PulseAudio::SoundLoop()
if (PulseInit())
{
while (m_run_thread.load() && m_pa_connected == 1 && m_pa_error >= 0)
while (m_run_thread.IsSet() && m_pa_connected == 1 && m_pa_error >= 0)
m_pa_error = pa_mainloop_iterate(m_pa_ml, 1, nullptr);
if (m_pa_error < 0)

View File

@ -8,10 +8,9 @@
#include <pulse/pulseaudio.h>
#endif
#include <atomic>
#include "AudioCommon/SoundStream.h"
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
#include "Common/Thread.h"
class PulseAudio final : public SoundStream
@ -41,7 +40,7 @@ private:
static void UnderflowCallback(pa_stream* s, void* userdata);
std::thread m_thread;
std::atomic<bool> m_run_thread;
Common::Flag m_run_thread;
bool m_stereo; // stereo, else surround
int m_bytespersample;

View File

@ -18,6 +18,7 @@
#include "Common/CPUDetect.h"
#include "Common/CommonPaths.h"
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
#include "Common/Logging/LogManager.h"
#include "Common/MathUtil.h"
#include "Common/MemoryUtil.h"
@ -101,7 +102,7 @@ void EmuThread();
static bool s_is_stopping = false;
static bool s_hardware_initialized = false;
static bool s_is_started = false;
static std::atomic<bool> s_is_booting{false};
static Common::Flag s_is_booting;
static void* s_window_handle = nullptr;
static std::string s_state_filename;
static std::thread s_emu_thread;
@ -469,7 +470,7 @@ static void FifoPlayerThread()
void EmuThread()
{
const SConfig& core_parameter = SConfig::GetInstance();
s_is_booting.store(true);
s_is_booting.Set();
Common::SetCurrentThreadName("Emuthread - Starting");
@ -488,7 +489,7 @@ void EmuThread()
if (!g_video_backend->Initialize(s_window_handle))
{
s_is_booting.store(false);
s_is_booting.Clear();
PanicAlert("Failed to initialize video backend!");
Host_Message(WM_USER_STOP);
return;
@ -503,7 +504,7 @@ void EmuThread()
if (!DSP::GetDSPEmulator()->Initialize(core_parameter.bWii, core_parameter.bDSPThread))
{
s_is_booting.store(false);
s_is_booting.Clear();
HW::Shutdown();
g_video_backend->Shutdown();
PanicAlert("Failed to initialize DSP emulation!");
@ -545,7 +546,7 @@ void EmuThread()
// The hardware is initialized.
s_hardware_initialized = true;
s_is_booting.store(false);
s_is_booting.Clear();
// Set execution state to known values (CPU/FIFO/Audio Paused)
CPU::Break();
@ -1024,7 +1025,7 @@ void HostDispatchJobs()
// CORE_UNINITIALIZED: s_is_booting -> s_hardware_initialized
// We need to check variables in the same order as the state
// transition, otherwise we race and get transient failures.
if (!job.run_after_stop && !s_is_booting.load() && !IsRunning())
if (!job.run_after_stop && !s_is_booting.IsSet() && !IsRunning())
continue;
guard.unlock();

View File

@ -2,7 +2,6 @@
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <atomic>
#include <memory>
#include <mutex>
#include <queue>
@ -21,7 +20,7 @@
u16 GeckoSockServer::server_port;
int GeckoSockServer::client_count;
std::thread GeckoSockServer::connectionThread;
std::atomic<bool> GeckoSockServer::server_running;
Common::Flag GeckoSockServer::server_running;
std::mutex GeckoSockServer::connection_lock;
std::queue<std::unique_ptr<sf::TcpSocket>> GeckoSockServer::waiting_socks;
@ -37,13 +36,13 @@ GeckoSockServer::~GeckoSockServer()
{
--client_count;
client_running.store(false);
client_running.Clear();
clientThread.join();
}
if (client_count <= 0)
{
server_running.store(false);
server_running.Clear();
connectionThread.join();
}
}
@ -54,14 +53,14 @@ void GeckoSockServer::GeckoConnectionWaiter()
sf::TcpListener server;
server_port = 0xd6ec; // "dolphin gecko"
for (int bind_tries = 0; bind_tries <= 10 && !server_running.load(); bind_tries++)
for (int bind_tries = 0; bind_tries <= 10 && !server_running.IsSet(); bind_tries++)
{
server_running.store(server.listen(server_port) == sf::Socket::Done);
if (!server_running.load())
server_running.Set(server.listen(server_port) == sf::Socket::Done);
if (!server_running.IsSet())
server_port++;
}
if (!server_running.load())
if (!server_running.IsSet())
return;
Core::DisplayMessage(StringFromFormat("USBGecko: Listening on TCP port %u", server_port), 5000);
@ -69,7 +68,7 @@ void GeckoSockServer::GeckoConnectionWaiter()
server.setBlocking(false);
auto new_client = std::make_unique<sf::TcpSocket>();
while (server_running.load())
while (server_running.IsSet())
{
if (server.accept(*new_client) == sf::Socket::Done)
{
@ -94,7 +93,7 @@ bool GeckoSockServer::GetAvailableSock()
client = std::move(waiting_socks.front());
if (clientThread.joinable())
{
client_running.store(false);
client_running.Clear();
clientThread.join();
recv_fifo = std::deque<u8>();
@ -111,13 +110,13 @@ bool GeckoSockServer::GetAvailableSock()
void GeckoSockServer::ClientThread()
{
client_running.store(true);
client_running.Set();
Common::SetCurrentThreadName("Gecko Client");
client->setBlocking(false);
while (client_running.load())
while (client_running.IsSet())
{
bool did_nothing = true;
@ -129,7 +128,7 @@ void GeckoSockServer::ClientThread()
std::size_t got = 0;
if (client->receive(&data[0], ArraySize(data), got) == sf::Socket::Disconnected)
client_running.store(false);
client_running.Clear();
if (got != 0)
{
@ -146,7 +145,7 @@ void GeckoSockServer::ClientThread()
send_fifo.clear();
if (client->send(&packet[0], packet.size()) == sf::Socket::Disconnected)
client_running.store(false);
client_running.Clear();
}
} // unlock transfer

View File

@ -5,7 +5,6 @@
#pragma once
#include <SFML/Network.hpp>
#include <atomic>
#include <deque>
#include <memory>
#include <mutex>
@ -13,6 +12,7 @@
#include <thread>
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
#include "Core/HW/EXI_Device.h"
class GeckoSockServer
@ -33,13 +33,13 @@ public:
private:
static int client_count;
std::atomic<bool> client_running;
Common::Flag client_running;
// Only ever one server thread
static void GeckoConnectionWaiter();
static u16 server_port;
static std::atomic<bool> server_running;
static Common::Flag server_running;
static std::thread connectionThread;
static std::mutex connection_lock;
static std::queue<std::unique_ptr<sf::TcpSocket>> waiting_socks;

View File

@ -205,19 +205,13 @@ void GCMemcardDirectory::FlushThread()
// no-op until signalled
m_flush_trigger.Wait();
if (m_exiting)
{
m_exiting = false;
if (m_exiting.TestAndClear())
return;
}
// no-op as long as signalled within flush_interval
while (m_flush_trigger.WaitFor(flush_interval))
{
if (m_exiting)
{
m_exiting = false;
if (m_exiting.TestAndClear())
return;
}
}
FlushToFile();
@ -226,7 +220,7 @@ void GCMemcardDirectory::FlushThread()
GCMemcardDirectory::~GCMemcardDirectory()
{
m_exiting = true;
m_exiting.Set();
m_flush_trigger.Set();
m_flush_thread.join();

View File

@ -4,7 +4,6 @@
#pragma once
#include <atomic>
#include <chrono>
#include <mutex>
#include <string>
@ -57,6 +56,6 @@ private:
const std::chrono::seconds flush_interval = std::chrono::seconds(1);
Common::Event m_flush_trigger;
std::mutex m_write_mutex;
std::atomic<bool> m_exiting;
Common::Flag m_exiting;
std::thread m_flush_thread;
};

View File

@ -326,7 +326,7 @@ void Wiimote::ConnectOnInput()
void Wiimote::Prepare()
{
m_need_prepare.store(true);
m_need_prepare.Set();
IOWakeup();
}
@ -521,47 +521,27 @@ void WiimoteScanner::ThreadFunc()
bool Wiimote::Connect(int index)
{
m_index = index;
m_need_prepare.store(true);
m_need_prepare.Set();
if (!m_run_thread.load())
if (!m_run_thread.IsSet())
{
m_thread_ready.store(false);
StartThread();
WaitReady();
m_thread_ready_event.Wait();
}
return IsConnected();
}
void Wiimote::StartThread()
{
m_run_thread.store(true);
m_wiimote_thread = std::thread(&Wiimote::ThreadFunc, this);
}
void Wiimote::StopThread()
{
m_run_thread.store(false);
if (!m_run_thread.TestAndClear())
return;
IOWakeup();
if (m_wiimote_thread.joinable())
m_wiimote_thread.join();
}
void Wiimote::SetReady()
{
if (!m_thread_ready.load())
{
m_thread_ready.store(true);
m_thread_ready_cond.notify_all();
}
}
void Wiimote::WaitReady()
{
std::unique_lock<std::mutex> lock(m_thread_ready_mutex);
while (!m_thread_ready.load())
{
m_thread_ready_cond.wait(lock);
}
m_wiimote_thread.join();
}
void Wiimote::ThreadFunc()
@ -577,7 +557,8 @@ void Wiimote::ThreadFunc()
ok = ConnectInternal();
}
SetReady();
m_thread_ready_event.Set();
m_run_thread.Set();
if (!ok)
{
@ -585,17 +566,13 @@ void Wiimote::ThreadFunc()
}
// main loop
while (IsConnected() && m_run_thread.load())
while (IsConnected() && m_run_thread.IsSet())
{
if (m_need_prepare.load())
if (m_need_prepare.TestAndClear() && !PrepareOnThread())
{
m_need_prepare.store(false);
if (!PrepareOnThread())
{
ERROR_LOG(WIIMOTE, "Wiimote::PrepareOnThread failed. Disconnecting Wiimote %d.",
m_index + 1);
break;
}
ERROR_LOG(WIIMOTE, "Wiimote::PrepareOnThread failed. Disconnecting Wiimote %d.",
m_index + 1);
break;
}
Write();
Read();

View File

@ -5,7 +5,6 @@
#pragma once
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <string>
#include <thread>
@ -95,20 +94,16 @@ private:
virtual void IOWakeup() = 0;
void ThreadFunc();
void SetReady();
void WaitReady();
bool m_rumble_state;
std::thread m_wiimote_thread;
// Whether to keep running the thread.
std::atomic<bool> m_run_thread{false};
Common::Flag m_run_thread;
// Whether to call PrepareOnThread.
std::atomic<bool> m_need_prepare{false};
// Whether the thread has finished ConnectInternal.
std::atomic<bool> m_thread_ready{false};
std::mutex m_thread_ready_mutex;
std::condition_variable m_thread_ready_cond;
Common::Flag m_need_prepare;
// Triggered when the thread has finished ConnectInternal.
Common::Event m_thread_ready_event;
Common::FifoQueue<Report> m_read_reports;
Common::FifoQueue<Report> m_write_reports;

View File

@ -36,12 +36,12 @@ NetSettings g_NetPlaySettings;
NetPlayClient::~NetPlayClient()
{
// not perfect
if (m_is_running.load())
if (m_is_running.IsSet())
StopGame();
if (m_is_connected)
{
m_do_loop.store(false);
m_do_loop.Clear();
m_thread.join();
}
@ -624,7 +624,7 @@ void NetPlayClient::SendAsync(std::unique_ptr<sf::Packet> packet)
// called from ---NETPLAY--- thread
void NetPlayClient::ThreadFunc()
{
while (m_do_loop.load())
while (m_do_loop.IsSet())
{
ENetEvent netEvent;
int net;
@ -650,7 +650,7 @@ void NetPlayClient::ThreadFunc()
case ENET_EVENT_TYPE_DISCONNECT:
m_dialog->OnConnectionLost();
if (m_is_running.load())
if (m_is_running.IsSet())
StopGame();
break;
@ -790,7 +790,7 @@ bool NetPlayClient::StartGame(const std::string& path)
std::lock_guard<std::recursive_mutex> lkg(m_crit.game);
SendStartGamePacket();
if (m_is_running.load())
if (m_is_running.IsSet())
{
PanicAlertT("Game is already running!");
return false;
@ -798,7 +798,7 @@ bool NetPlayClient::StartGame(const std::string& path)
m_timebase_frame = 0;
m_is_running.store(true);
m_is_running.Set();
NetPlay_Enable(this);
ClearBuffers();
@ -998,7 +998,7 @@ bool NetPlayClient::GetNetPads(const u8 pad_nb, GCPadStatus* pad_status)
// other clients to send it to us
while (m_pad_buffer[pad_nb].Size() == 0)
{
if (!m_is_running.load())
if (!m_is_running.IsSet())
{
return false;
}
@ -1047,7 +1047,7 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size)
while (m_wiimote_buffer[_number].Size() == 0)
{
if (!m_is_running.load())
if (!m_is_running.IsSet())
{
return false;
}
@ -1067,7 +1067,7 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size)
{
while (m_wiimote_buffer[_number].Size() == 0)
{
if (!m_is_running.load())
if (!m_is_running.IsSet())
{
return false;
}
@ -1098,7 +1098,7 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const u8 size)
// called from ---GUI--- thread and ---NETPLAY--- thread (client side)
bool NetPlayClient::StopGame()
{
m_is_running.store(false);
m_is_running.Clear();
// stop waiting for input
m_gc_pad_event.Set();
@ -1115,10 +1115,10 @@ bool NetPlayClient::StopGame()
// called from ---GUI--- thread
void NetPlayClient::Stop()
{
if (!m_is_running.load())
if (!m_is_running.IsSet())
return;
m_is_running.store(false);
m_is_running.Clear();
// stop waiting for input
m_gc_pad_event.Set();

View File

@ -6,7 +6,6 @@
#include <SFML/Network/Packet.hpp>
#include <array>
#include <atomic>
#include <map>
#include <memory>
#include <mutex>
@ -124,8 +123,8 @@ protected:
std::thread m_thread;
std::string m_selected_game;
std::atomic<bool> m_is_running{false};
std::atomic<bool> m_do_loop{true};
Common::Flag m_is_running{false};
Common::Flag m_do_loop{true};
unsigned int m_target_buffer_size = 20;

View File

@ -19,7 +19,7 @@ AsyncRequests::AsyncRequests() : m_enable(false), m_passthrough(true)
void AsyncRequests::PullEventsInternal()
{
std::unique_lock<std::mutex> lock(m_mutex);
m_empty.store(true);
m_empty.Set();
while (!m_queue.empty())
{
@ -76,7 +76,7 @@ void AsyncRequests::PushEvent(const AsyncRequests::Event& event, bool blocking)
return;
}
m_empty.store(false);
m_empty.Clear();
m_wake_me_up_again |= blocking;
if (!m_enable)

View File

@ -4,13 +4,13 @@
#pragma once
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <vector>
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
struct EfbPokeData;
@ -70,7 +70,7 @@ public:
void PullEvents()
{
if (!m_empty.load())
if (!m_empty.IsSet())
PullEventsInternal();
}
void PushEvent(const Event& event, bool blocking = false);
@ -84,7 +84,7 @@ private:
static AsyncRequests s_singleton;
std::atomic<bool> m_empty;
Common::Flag m_empty;
std::queue<Event> m_queue;
std::mutex m_mutex;
std::condition_variable m_cond;

View File

@ -9,6 +9,7 @@
#include "Common/Atomic.h"
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
#include "Common/Logging/Log.h"
#include "Core/ConfigManager.h"
#include "Core/CoreTiming.h"
@ -36,8 +37,8 @@ static u16 m_bboxright;
static u16 m_bboxbottom;
static u16 m_tokenReg;
static std::atomic<bool> s_interrupt_set;
static std::atomic<bool> s_interrupt_waiting;
static Common::Flag s_interrupt_set;
static Common::Flag s_interrupt_waiting;
static bool IsOnThread()
{
@ -106,8 +107,8 @@ void Init()
fifo.bFF_LoWatermark = 0;
fifo.bFF_LoWatermarkInt = 0;
s_interrupt_set.store(false);
s_interrupt_waiting.store(false);
s_interrupt_set.Clear();
s_interrupt_waiting.Clear();
et_UpdateInterrupts = CoreTiming::RegisterEvent("CPInterrupt", UpdateInterrupts_Wrapper);
}
@ -324,18 +325,18 @@ void UpdateInterrupts(u64 userdata)
{
if (userdata)
{
s_interrupt_set.store(true);
s_interrupt_set.Set();
INFO_LOG(COMMANDPROCESSOR, "Interrupt set");
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
}
else
{
s_interrupt_set.store(false);
s_interrupt_set.Clear();
INFO_LOG(COMMANDPROCESSOR, "Interrupt cleared");
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
}
CoreTiming::ForceExceptionCheck(0);
s_interrupt_waiting.store(false);
s_interrupt_waiting.Clear();
Fifo::RunGpu();
}
@ -347,7 +348,7 @@ void UpdateInterruptsFromVideoBackend(u64 userdata)
bool IsInterruptWaiting()
{
return s_interrupt_waiting.load();
return s_interrupt_waiting.IsSet();
}
void SetCPStatusFromGPU()
@ -387,7 +388,7 @@ void SetCPStatusFromGPU()
bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable;
if (interrupt != s_interrupt_set.load() && !s_interrupt_waiting.load())
if (interrupt != s_interrupt_set.IsSet() && !s_interrupt_waiting.IsSet())
{
u64 userdata = interrupt ? 1 : 0;
if (IsOnThread())
@ -395,7 +396,7 @@ void SetCPStatusFromGPU()
if (!interrupt || bpInt || undfInt || ovfInt)
{
// Schedule the interrupt asynchronously
s_interrupt_waiting.store(true);
s_interrupt_waiting.Set();
CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
}
}
@ -418,14 +419,14 @@ void SetCPStatusFromCPU()
bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable;
if (interrupt != s_interrupt_set.load() && !s_interrupt_waiting.load())
if (interrupt != s_interrupt_set.IsSet() && !s_interrupt_waiting.IsSet())
{
u64 userdata = interrupt ? 1 : 0;
if (IsOnThread())
{
if (!interrupt || bpInt || undfInt || ovfInt)
{
s_interrupt_set.store(interrupt);
s_interrupt_set.Set(interrupt);
INFO_LOG(COMMANDPROCESSOR, "Interrupt set");
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, interrupt);
}

View File

@ -36,7 +36,7 @@ static bool s_skip_current_frame = false;
static Common::BlockingLoop s_gpu_mainloop;
static std::atomic<bool> s_emu_running_state;
static Common::Flag s_emu_running_state;
// Most of this array is unlikely to be faulted in...
static u8 s_fifo_aux_data[FIFO_SIZE];
@ -147,13 +147,13 @@ void ExitGpuLoop()
FlushGpu();
// Terminate GPU thread loop
s_emu_running_state.store(true);
s_emu_running_state.Set();
s_gpu_mainloop.Stop(false);
}
void EmulatorState(bool running)
{
s_emu_running_state.store(running);
s_emu_running_state.Set(running);
if (running)
s_gpu_mainloop.Wakeup();
else
@ -307,7 +307,7 @@ void RunGpuLoop()
g_video_backend->PeekMessages();
// Do nothing while paused
if (!s_emu_running_state.load())
if (!s_emu_running_state.IsSet())
return;
if (s_use_deterministic_gpu_thread)