mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Use atomic variables for thread synchronization where useful.
parent
05bc2ed7cb
commit
94c5269fa7
|
@ -18,16 +18,14 @@
|
||||||
#include "network_internal.h"
|
#include "network_internal.h"
|
||||||
#include "network_udp.h"
|
#include "network_udp.h"
|
||||||
#include "network_gamelist.h"
|
#include "network_gamelist.h"
|
||||||
#include <mutex>
|
#include <atomic>
|
||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
||||||
NetworkGameList *_network_game_list = NULL;
|
NetworkGameList *_network_game_list = NULL;
|
||||||
|
|
||||||
/** Mutex for handling delayed insertion/querying of servers. */
|
|
||||||
static std::mutex _network_game_list_mutex;
|
|
||||||
/** The games to insert when the GUI thread has time for us. */
|
/** The games to insert when the GUI thread has time for us. */
|
||||||
static NetworkGameList *_network_game_delayed_insertion_list = NULL;
|
static std::atomic<NetworkGameList *> _network_game_delayed_insertion_list(NULL);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new item to the linked gamelist, but do it delayed in the next tick
|
* Add a new item to the linked gamelist, but do it delayed in the next tick
|
||||||
|
@ -36,18 +34,17 @@ static NetworkGameList *_network_game_delayed_insertion_list = NULL;
|
||||||
*/
|
*/
|
||||||
void NetworkGameListAddItemDelayed(NetworkGameList *item)
|
void NetworkGameListAddItemDelayed(NetworkGameList *item)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_network_game_list_mutex);
|
item->next = _network_game_delayed_insertion_list.load(std::memory_order_relaxed);
|
||||||
item->next = _network_game_delayed_insertion_list;
|
while (!_network_game_delayed_insertion_list.compare_exchange_weak(item->next, item, std::memory_order_acq_rel)) {}
|
||||||
_network_game_delayed_insertion_list = item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Perform the delayed (thread safe) insertion into the game list */
|
/** Perform the delayed (thread safe) insertion into the game list */
|
||||||
static void NetworkGameListHandleDelayedInsert()
|
static void NetworkGameListHandleDelayedInsert()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_network_game_list_mutex);
|
while (true) {
|
||||||
while (_network_game_delayed_insertion_list != NULL) {
|
NetworkGameList *ins_item = _network_game_delayed_insertion_list.load(std::memory_order_relaxed);
|
||||||
NetworkGameList *ins_item = _network_game_delayed_insertion_list;
|
while (ins_item != NULL && !_network_game_delayed_insertion_list.compare_exchange_weak(ins_item, ins_item->next, std::memory_order_acq_rel)) {}
|
||||||
_network_game_delayed_insertion_list = ins_item->next;
|
if (ins_item == NULL) break; // No item left.
|
||||||
|
|
||||||
NetworkGameList *item = NetworkGameListAddItem(ins_item->address);
|
NetworkGameList *item = NetworkGameListAddItem(ins_item->address);
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#include "../string_func.h"
|
#include "../string_func.h"
|
||||||
#include "../fios.h"
|
#include "../fios.h"
|
||||||
#include "../error.h"
|
#include "../error.h"
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
|
@ -370,9 +371,9 @@ void NORETURN SlErrorCorruptFmt(const char *format, ...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typedef void (*AsyncSaveFinishProc)(); ///< Callback for when the savegame loading is finished.
|
typedef void (*AsyncSaveFinishProc)(); ///< Callback for when the savegame loading is finished.
|
||||||
static AsyncSaveFinishProc _async_save_finish = NULL; ///< Callback to call when the savegame loading is finished.
|
static std::atomic<AsyncSaveFinishProc> _async_save_finish; ///< Callback to call when the savegame loading is finished.
|
||||||
static std::thread _save_thread; ///< The thread we're using to compress and write a savegame
|
static std::thread _save_thread; ///< The thread we're using to compress and write a savegame
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by save thread to tell we finished saving.
|
* Called by save thread to tell we finished saving.
|
||||||
|
@ -381,9 +382,9 @@ static std::thread _save_thread; ///< The thread we're usin
|
||||||
static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
|
static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
|
||||||
{
|
{
|
||||||
if (_exit_game) return;
|
if (_exit_game) return;
|
||||||
while (_async_save_finish != NULL) CSleep(10);
|
while (_async_save_finish.load(std::memory_order_acquire) != NULL) CSleep(10);
|
||||||
|
|
||||||
_async_save_finish = proc;
|
_async_save_finish.store(proc, std::memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -391,11 +392,10 @@ static void SetAsyncSaveFinish(AsyncSaveFinishProc proc)
|
||||||
*/
|
*/
|
||||||
void ProcessAsyncSaveFinish()
|
void ProcessAsyncSaveFinish()
|
||||||
{
|
{
|
||||||
if (_async_save_finish == NULL) return;
|
AsyncSaveFinishProc proc = _async_save_finish.exchange(NULL, std::memory_order_acq_rel);
|
||||||
|
if (proc == NULL) return;
|
||||||
|
|
||||||
_async_save_finish();
|
proc();
|
||||||
|
|
||||||
_async_save_finish = NULL;
|
|
||||||
|
|
||||||
if (_save_thread.joinable()) {
|
if (_save_thread.joinable()) {
|
||||||
_save_thread.join();
|
_save_thread.join();
|
||||||
|
|
Loading…
Reference in New Issue