Use std::thread, std::mutex and std::condition_variable everywhere
This commit is contained in:
parent
b6e9fcd801
commit
9157fb43f0
@ -29,11 +29,12 @@
|
||||
#include "utils/string_utils.hpp"
|
||||
#include "utils/vs.hpp"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits>
|
||||
@ -91,28 +92,9 @@ SFXManager::SFXManager()
|
||||
#ifdef ENABLE_SOUND
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
pthread_cond_init(&m_cond_request, NULL);
|
||||
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
m_thread_id.setAtomic(new pthread_t());
|
||||
// The thread is created even if there atm sfx are disabled
|
||||
// (since the user might enable it later).
|
||||
int error = pthread_create(m_thread_id.getData(), &attr,
|
||||
&SFXManager::mainLoop, this);
|
||||
if (error)
|
||||
{
|
||||
m_thread_id.lock();
|
||||
delete m_thread_id.getData();
|
||||
m_thread_id.unlock();
|
||||
m_thread_id.setAtomic(0);
|
||||
Log::error("SFXManager", "Could not create thread, error=%d.",
|
||||
errno);
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
m_thread = std::thread(std::bind(mainLoop, this));
|
||||
setMasterSFXVolume( UserConfigParams::m_sfx_volume );
|
||||
m_sfx_commands.lock();
|
||||
m_sfx_commands.getData().clear();
|
||||
@ -129,11 +111,7 @@ SFXManager::~SFXManager()
|
||||
#ifdef ENABLE_SOUND
|
||||
if (UserConfigParams::m_enable_sound)
|
||||
{
|
||||
m_thread_id.lock();
|
||||
pthread_join(*m_thread_id.getData(), NULL);
|
||||
delete m_thread_id.getData();
|
||||
m_thread_id.unlock();
|
||||
pthread_cond_destroy(&m_cond_request);
|
||||
m_thread.join();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -346,7 +324,7 @@ void SFXManager::stopThread()
|
||||
{
|
||||
queue(SFX_EXIT);
|
||||
// Make sure the thread wakes up.
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
m_condition_variable.notify_one();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@ -361,16 +339,16 @@ void SFXManager::stopThread()
|
||||
* in order to avoid rendering delays.
|
||||
* \param obj A pointer to the SFX singleton.
|
||||
*/
|
||||
void* SFXManager::mainLoop(void *obj)
|
||||
void SFXManager::mainLoop(void *obj)
|
||||
{
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!UserConfigParams::m_enable_sound)
|
||||
return NULL;
|
||||
return;
|
||||
|
||||
VS::setThreadName("SFXManager");
|
||||
SFXManager *me = (SFXManager*)obj;
|
||||
|
||||
me->m_sfx_commands.lock();
|
||||
std::unique_lock<std::mutex> ul = me->m_sfx_commands.acquireMutex();
|
||||
|
||||
// Wait till we have an empty sfx in the queue
|
||||
while (me->m_sfx_commands.getData().empty() ||
|
||||
@ -384,7 +362,7 @@ void* SFXManager::mainLoop(void *obj)
|
||||
// (pthread_cond_wait man page)!
|
||||
while (empty)
|
||||
{
|
||||
pthread_cond_wait(&me->m_cond_request, me->m_sfx_commands.getMutex());
|
||||
me->m_condition_variable.wait(ul);
|
||||
empty = me->m_sfx_commands.getData().empty();
|
||||
}
|
||||
SFXCommand *current = me->m_sfx_commands.getData().front();
|
||||
@ -395,7 +373,7 @@ void* SFXManager::mainLoop(void *obj)
|
||||
delete current;
|
||||
break;
|
||||
}
|
||||
me->m_sfx_commands.unlock();
|
||||
ul.unlock();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
PROFILER_PUSH_CPU_MARKER("Execute", 0, 255, 0);
|
||||
switch (current->m_command)
|
||||
@ -473,7 +451,7 @@ void* SFXManager::mainLoop(void *obj)
|
||||
t = StkTime::getMonoTimeMs() - t;
|
||||
me->queue(SFX_UPDATE, (SFXBase*)NULL, float(t / 1000.0));
|
||||
}
|
||||
me->m_sfx_commands.lock();
|
||||
ul = me->m_sfx_commands.acquireMutex();
|
||||
PROFILER_POP_CPU_MARKER();
|
||||
} // while
|
||||
|
||||
@ -488,9 +466,8 @@ void* SFXManager::mainLoop(void *obj)
|
||||
delete me->m_sfx_commands.getData().front();
|
||||
me->m_sfx_commands.getData().erase(me->m_sfx_commands.getData().begin());
|
||||
}
|
||||
me->m_sfx_commands.unlock();
|
||||
#endif
|
||||
return NULL;
|
||||
return;
|
||||
} // mainLoop
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@ -812,7 +789,7 @@ void SFXManager::update()
|
||||
|
||||
queue(SFX_UPDATE, (SFXBase*)NULL);
|
||||
// Wake up the sfx thread to handle all queued up audio commands.
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
m_condition_variable.notify_one();
|
||||
#endif
|
||||
} // update
|
||||
|
||||
@ -1088,7 +1065,7 @@ SFXBase* SFXManager::quickSound(const std::string &sound_type)
|
||||
#ifdef ENABLE_SOUND
|
||||
if (!sfxAllowed()) return NULL;
|
||||
|
||||
MutexLockerHelper lock(m_quick_sounds);
|
||||
std::unique_lock<std::mutex> ul = m_quick_sounds.acquireMutex();
|
||||
std::map<std::string, SFXBase*>::iterator sound =
|
||||
m_quick_sounds.getData().find(sound_type);
|
||||
|
||||
|
@ -25,8 +25,11 @@
|
||||
#include "utils/synchronised.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#ifdef ENABLE_SOUND
|
||||
@ -219,18 +222,18 @@ private:
|
||||
float m_master_gain;
|
||||
|
||||
/** Thread id of the thread running in this object. */
|
||||
Synchronised<pthread_t *> m_thread_id;
|
||||
std::thread m_thread;
|
||||
|
||||
uint64_t m_last_update_time;
|
||||
|
||||
/** A conditional variable to wake up the main loop. */
|
||||
pthread_cond_t m_cond_request;
|
||||
std::condition_variable m_condition_variable;
|
||||
|
||||
void loadSfx();
|
||||
SFXManager();
|
||||
virtual ~SFXManager();
|
||||
|
||||
static void* mainLoop(void *obj);
|
||||
static void mainLoop(void *obj);
|
||||
void deleteSFX(SFXBase *sfx);
|
||||
void queueCommand(SFXCommand *command);
|
||||
void reallyPositionListenerNow();
|
||||
|
@ -41,11 +41,9 @@
|
||||
# include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
Synchronised<FILE*>Network::m_log_file = NULL;
|
||||
Synchronised<FILE*>Network::m_log_file;
|
||||
bool Network::m_connection_debug = false;
|
||||
|
||||
// ============================================================================
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "utils/vs.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
@ -74,18 +75,13 @@ namespace Online
|
||||
m_game_polling_interval = 60; // same for game polling
|
||||
m_time_since_poll = m_menu_polling_interval;
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
pthread_cond_init(&m_cond_request, NULL);
|
||||
m_abort.setAtomic(false);
|
||||
} // RequestManager
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
RequestManager::~RequestManager()
|
||||
{
|
||||
m_thread_id.lock();
|
||||
pthread_join(*m_thread_id.getData(), NULL);
|
||||
delete m_thread_id.getData();
|
||||
m_thread_id.unlock();
|
||||
pthread_cond_destroy(&m_cond_request);
|
||||
m_thread.join();
|
||||
curl_global_cleanup();
|
||||
} // ~RequestManager
|
||||
|
||||
@ -101,24 +97,7 @@ namespace Online
|
||||
*/
|
||||
void RequestManager::startNetworkThread()
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
|
||||
|
||||
m_thread_id.setAtomic(new pthread_t());
|
||||
int error = pthread_create(m_thread_id.getData(), &attr,
|
||||
&RequestManager::mainLoop, this);
|
||||
if (error)
|
||||
{
|
||||
m_thread_id.lock();
|
||||
delete m_thread_id.getData();
|
||||
m_thread_id.unlock();
|
||||
m_thread_id.setAtomic(0);
|
||||
Log::error("HTTP Manager", "Could not create thread, error=%d.",
|
||||
errno);
|
||||
}
|
||||
pthread_attr_destroy(&attr);
|
||||
|
||||
m_thread = std::thread(std::bind(mainLoop, this));
|
||||
// In case that login id was not saved (or first start of stk),
|
||||
// current player would not be defined at this stage.
|
||||
PlayerProfile *player = PlayerManager::getCurrentPlayer();
|
||||
@ -181,7 +160,7 @@ namespace Online
|
||||
m_request_queue.getData().push(request);
|
||||
|
||||
// Wake up the network http thread
|
||||
pthread_cond_signal(&m_cond_request);
|
||||
m_condition_variable.notify_one();
|
||||
m_request_queue.unlock();
|
||||
} // addRequest
|
||||
|
||||
@ -191,13 +170,13 @@ namespace Online
|
||||
* of packages to download, it will wait for commands to be issued.
|
||||
* \param obj: A pointer to this object, passed on by pthread_create
|
||||
*/
|
||||
void *RequestManager::mainLoop(void *obj)
|
||||
void RequestManager::mainLoop(void *obj)
|
||||
{
|
||||
VS::setThreadName("RequestManager");
|
||||
RequestManager *me = (RequestManager*) obj;
|
||||
|
||||
me->m_current_request = nullptr;
|
||||
me->m_request_queue.lock();
|
||||
std::unique_lock<std::mutex> ul = me->m_request_queue.acquireMutex();
|
||||
while (me->m_request_queue.getData().empty() ||
|
||||
me->m_request_queue.getData().top()->getType() != Request::RT_QUIT)
|
||||
{
|
||||
@ -208,7 +187,7 @@ namespace Online
|
||||
// (pthread_cond_wait man page)!
|
||||
while (empty)
|
||||
{
|
||||
pthread_cond_wait(&me->m_cond_request, me->m_request_queue.getMutex());
|
||||
me->m_condition_variable.wait(ul);
|
||||
empty = me->m_request_queue.getData().empty();
|
||||
}
|
||||
// We pause the request manager thread when going into background in iOS
|
||||
@ -223,14 +202,14 @@ namespace Online
|
||||
break;
|
||||
}
|
||||
|
||||
me->m_request_queue.unlock();
|
||||
ul.unlock();
|
||||
me->m_current_request->execute();
|
||||
// This test is necessary in case that execute() was aborted
|
||||
// (otherwise the assert in addResult will be triggered).
|
||||
if (!me->getAbort())
|
||||
me->addResult(me->m_current_request);
|
||||
me->m_current_request = nullptr;
|
||||
me->m_request_queue.lock();
|
||||
ul = me->m_request_queue.acquireMutex();
|
||||
} // while handle all requests
|
||||
|
||||
// Signal that the request manager can now be deleted.
|
||||
@ -243,10 +222,6 @@ namespace Online
|
||||
{
|
||||
me->m_request_queue.getData().pop();
|
||||
}
|
||||
me->m_request_queue.unlock();
|
||||
pthread_exit(NULL);
|
||||
|
||||
return 0;
|
||||
} // mainLoop
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
|
@ -34,10 +34,11 @@
|
||||
#endif
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <curl/curl.h>
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <pthread.h>
|
||||
#include <thread>
|
||||
|
||||
namespace Online
|
||||
{
|
||||
@ -99,7 +100,7 @@ namespace Online
|
||||
std::shared_ptr<Online::Request> m_current_request;
|
||||
|
||||
/** A conditional variable to wake up the main loop. */
|
||||
pthread_cond_t m_cond_request;
|
||||
std::condition_variable m_condition_variable;
|
||||
|
||||
/** Signal an abort in case that a download is still happening. */
|
||||
Synchronised<bool> m_abort;
|
||||
@ -114,7 +115,7 @@ namespace Online
|
||||
float m_menu_polling_interval;
|
||||
|
||||
/** Thread id of the thread running in this object. */
|
||||
Synchronised<pthread_t *> m_thread_id;
|
||||
std::thread m_thread;
|
||||
|
||||
/** The list of pointers to all requests that still need to be
|
||||
* handled. */
|
||||
@ -133,7 +134,7 @@ namespace Online
|
||||
void addResult(std::shared_ptr<Online::Request> request);
|
||||
void handleResultQueue();
|
||||
|
||||
static void *mainLoop(void *obj);
|
||||
static void mainLoop(void *obj);
|
||||
|
||||
RequestManager(); //const std::string &url
|
||||
~RequestManager();
|
||||
|
@ -18,8 +18,6 @@
|
||||
|
||||
#include "states_screens/dialogs/addons_loading.hpp"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "addons/addons_manager.hpp"
|
||||
#include "config/player_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
|
@ -19,24 +19,16 @@
|
||||
#ifndef HEADER_SYNCHRONISED_HPP
|
||||
#define HEADER_SYNCHRONISED_HPP
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
class ISynchronised
|
||||
{
|
||||
public :
|
||||
virtual ~ISynchronised() {}
|
||||
virtual void lock() const = 0 ;
|
||||
virtual void unlock() const = 0;
|
||||
};
|
||||
#include <mutex>
|
||||
|
||||
/** A variable that is automatically synchronised using pthreads mutex.
|
||||
*/
|
||||
template<typename TYPE>
|
||||
class Synchronised : public ISynchronised
|
||||
class Synchronised
|
||||
{
|
||||
private:
|
||||
/** The mutex to protect this variable with. */
|
||||
mutable pthread_mutex_t m_mutex;
|
||||
mutable std::mutex m_mutex;
|
||||
/** The actual data to be used. */
|
||||
TYPE m_data;
|
||||
public:
|
||||
@ -44,7 +36,6 @@ public:
|
||||
/** Initialise the data and the mutex with default constructors. */
|
||||
Synchronised() : m_data()
|
||||
{
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
} // Synchronised()
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -52,7 +43,6 @@ public:
|
||||
Synchronised(const TYPE &v)
|
||||
{
|
||||
m_data = v;
|
||||
pthread_mutex_init(&m_mutex, NULL);
|
||||
} // Synchronised
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -60,7 +50,6 @@ public:
|
||||
*/
|
||||
~Synchronised()
|
||||
{
|
||||
pthread_mutex_destroy(&m_mutex);
|
||||
} // ~Synchronised
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -69,9 +58,8 @@ public:
|
||||
*/
|
||||
void setAtomic(const TYPE &v)
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_data = v;
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
} // set
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
@ -80,9 +68,9 @@ public:
|
||||
TYPE getAtomic() const
|
||||
{
|
||||
TYPE v;
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
std::unique_lock<std::mutex> ul(m_mutex);
|
||||
v = m_data;
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
ul.unlock();
|
||||
return v;
|
||||
} // get
|
||||
// ------------------------------------------------------------------------
|
||||
@ -104,37 +92,20 @@ public:
|
||||
/** Locks the mutex. Note that calls to get() or set() will fail, since
|
||||
* they will try to lock the mutex as well!
|
||||
*/
|
||||
void lock() const { pthread_mutex_lock(&m_mutex); }
|
||||
void lock() const { m_mutex.lock(); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Unlocks the mutex.
|
||||
*/
|
||||
void unlock() const {pthread_mutex_unlock(&m_mutex); }
|
||||
void unlock() const { m_mutex.unlock(); }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Gives access to the mutex, which can then be used in other pthread
|
||||
* calls (e.g. pthread_cond_wait).
|
||||
*/
|
||||
pthread_mutex_t* getMutex() { return &m_mutex; }
|
||||
/** Gives unique_lock to the mutex, which can then be used by
|
||||
* std::condition_variable wait. */
|
||||
std::unique_lock<std::mutex> acquireMutex() const
|
||||
{ return std::unique_lock<std::mutex>(m_mutex); }
|
||||
private:
|
||||
// Make sure that no actual copying is taking place
|
||||
// ------------------------------------------------------------------------
|
||||
void operator=(const Synchronised<TYPE>& v) {}
|
||||
};
|
||||
|
||||
#define MutexLocker(x) MutexLockerHelper __dummy(x);
|
||||
|
||||
class MutexLockerHelper
|
||||
{
|
||||
const ISynchronised * m_synchronised;
|
||||
public:
|
||||
MutexLockerHelper(const ISynchronised & synchronised){
|
||||
m_synchronised = &synchronised;
|
||||
m_synchronised->lock();
|
||||
}
|
||||
|
||||
~MutexLockerHelper(){
|
||||
m_synchronised->unlock();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user