mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-30 19:29:52 +02:00
Use C++11 threads
This commit is contained in:
@@ -21,8 +21,6 @@ namespace http
|
|||||||
post_fields_last(NULL)
|
post_fields_last(NULL)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
pthread_cond_init(&done_cv, NULL);
|
|
||||||
pthread_mutex_init(&rm_mutex, NULL);
|
|
||||||
easy = curl_easy_init();
|
easy = curl_easy_init();
|
||||||
RequestManager::Ref().AddRequest(this);
|
RequestManager::Ref().AddRequest(this);
|
||||||
}
|
}
|
||||||
@@ -36,8 +34,6 @@ namespace http
|
|||||||
curl_formfree(post_fields_first);
|
curl_formfree(post_fields_first);
|
||||||
#endif
|
#endif
|
||||||
curl_slist_free_all(headers);
|
curl_slist_free_all(headers);
|
||||||
pthread_mutex_destroy(&rm_mutex);
|
|
||||||
pthread_cond_destroy(&done_cv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Request::AddHeader(ByteString name, ByteString value)
|
void Request::AddHeader(ByteString name, ByteString value)
|
||||||
@@ -179,9 +175,10 @@ namespace http
|
|||||||
curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, Request::WriteDataHandler);
|
curl_easy_setopt(easy, CURLOPT_WRITEFUNCTION, Request::WriteDataHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&rm_mutex);
|
{
|
||||||
rm_started = true;
|
std::lock_guard<std::mutex> g(rm_mutex);
|
||||||
pthread_mutex_unlock(&rm_mutex);
|
rm_started = true;
|
||||||
|
}
|
||||||
RequestManager::Ref().StartRequest(this);
|
RequestManager::Ref().StartRequest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -194,19 +191,18 @@ namespace http
|
|||||||
return ""; // shouldn't happen but just in case
|
return ""; // shouldn't happen but just in case
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&rm_mutex);
|
ByteString response_out;
|
||||||
while (!rm_finished)
|
|
||||||
{
|
{
|
||||||
pthread_cond_wait(&done_cv, &rm_mutex);
|
std::unique_lock<std::mutex> l(rm_mutex);
|
||||||
|
done_cv.wait(l, [this]() { return rm_finished; });
|
||||||
|
rm_started = false;
|
||||||
|
rm_canceled = true;
|
||||||
|
if (status_out)
|
||||||
|
{
|
||||||
|
*status_out = status;
|
||||||
|
}
|
||||||
|
response_out = std::move(response_body);
|
||||||
}
|
}
|
||||||
rm_started = false;
|
|
||||||
rm_canceled = true;
|
|
||||||
if (status_out)
|
|
||||||
{
|
|
||||||
*status_out = status;
|
|
||||||
}
|
|
||||||
ByteString response_out = std::move(response_body);
|
|
||||||
pthread_mutex_unlock(&rm_mutex);
|
|
||||||
|
|
||||||
RequestManager::Ref().RemoveRequest(this);
|
RequestManager::Ref().RemoveRequest(this);
|
||||||
return response_out;
|
return response_out;
|
||||||
@@ -214,7 +210,7 @@ namespace http
|
|||||||
|
|
||||||
void Request::CheckProgress(int *total, int *done)
|
void Request::CheckProgress(int *total, int *done)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rm_mutex);
|
std::lock_guard<std::mutex> g(rm_mutex);
|
||||||
if (total)
|
if (total)
|
||||||
{
|
{
|
||||||
*total = rm_total;
|
*total = rm_total;
|
||||||
@@ -223,43 +219,37 @@ namespace http
|
|||||||
{
|
{
|
||||||
*done = rm_done;
|
*done = rm_done;
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&rm_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the request has finished
|
// returns true if the request has finished
|
||||||
bool Request::CheckDone()
|
bool Request::CheckDone()
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rm_mutex);
|
std::lock_guard<std::mutex> g(rm_mutex);
|
||||||
bool ret = rm_finished;
|
return rm_finished;
|
||||||
pthread_mutex_unlock(&rm_mutex);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the request was canceled
|
// returns true if the request was canceled
|
||||||
bool Request::CheckCanceled()
|
bool Request::CheckCanceled()
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rm_mutex);
|
std::lock_guard<std::mutex> g(rm_mutex);
|
||||||
bool ret = rm_canceled;
|
return rm_canceled;
|
||||||
pthread_mutex_unlock(&rm_mutex);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the request is running
|
// returns true if the request is running
|
||||||
bool Request::CheckStarted()
|
bool Request::CheckStarted()
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rm_mutex);
|
std::lock_guard<std::mutex> g(rm_mutex);
|
||||||
bool ret = rm_started;
|
return rm_started;
|
||||||
pthread_mutex_unlock(&rm_mutex);
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cancels the request, the request thread will delete the Request* when it finishes (do not use Request in any way after canceling)
|
// cancels the request, the request thread will delete the Request* when it finishes (do not use Request in any way after canceling)
|
||||||
void Request::Cancel()
|
void Request::Cancel()
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rm_mutex);
|
{
|
||||||
rm_canceled = true;
|
std::lock_guard<std::mutex> g(rm_mutex);
|
||||||
pthread_mutex_unlock(&rm_mutex);
|
rm_canceled = true;
|
||||||
|
}
|
||||||
RequestManager::Ref().RemoveRequest(this);
|
RequestManager::Ref().RemoveRequest(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,10 +3,10 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "common/tpt-minmax.h" // for MSVC, ensures windows.h doesn't cause compile errors by defining min/max
|
#include "common/tpt-minmax.h" // for MSVC, ensures windows.h doesn't cause compile errors by defining min/max
|
||||||
#include "common/tpt-thread.h"
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include "common/String.h"
|
#include "common/String.h"
|
||||||
#undef GetUserName // pthreads defines this, breaks stuff
|
|
||||||
|
|
||||||
#if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 55, 0)
|
#if defined(CURL_AT_LEAST_VERSION) && CURL_AT_LEAST_VERSION(7, 55, 0)
|
||||||
# define REQUEST_USE_CURL_OFFSET_T
|
# define REQUEST_USE_CURL_OFFSET_T
|
||||||
@@ -32,7 +32,7 @@ namespace http
|
|||||||
volatile bool rm_finished;
|
volatile bool rm_finished;
|
||||||
volatile bool rm_canceled;
|
volatile bool rm_canceled;
|
||||||
volatile bool rm_started;
|
volatile bool rm_started;
|
||||||
pthread_mutex_t rm_mutex;
|
std::mutex rm_mutex;
|
||||||
|
|
||||||
bool added_to_multi;
|
bool added_to_multi;
|
||||||
int status;
|
int status;
|
||||||
@@ -46,7 +46,7 @@ namespace http
|
|||||||
std::map<ByteString, ByteString> post_fields_map;
|
std::map<ByteString, ByteString> post_fields_map;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pthread_cond_t done_cv;
|
std::condition_variable done_cv;
|
||||||
|
|
||||||
static size_t WriteDataHandler(char * ptr, size_t size, size_t count, void * userdata);
|
static size_t WriteDataHandler(char * ptr, size_t size, size_t count, void * userdata);
|
||||||
|
|
||||||
|
@@ -21,36 +21,27 @@ namespace http
|
|||||||
rt_shutting_down(false),
|
rt_shutting_down(false),
|
||||||
multi(NULL)
|
multi(NULL)
|
||||||
{
|
{
|
||||||
pthread_cond_init(&rt_cv, NULL);
|
|
||||||
pthread_mutex_init(&rt_mutex, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestManager::~RequestManager()
|
RequestManager::~RequestManager()
|
||||||
{
|
{
|
||||||
pthread_mutex_destroy(&rt_mutex);
|
|
||||||
pthread_cond_destroy(&rt_cv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestManager::Shutdown()
|
void RequestManager::Shutdown()
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rt_mutex);
|
{
|
||||||
rt_shutting_down = true;
|
std::lock_guard<std::mutex> g(rt_mutex);
|
||||||
pthread_cond_signal(&rt_cv);
|
rt_shutting_down = true;
|
||||||
pthread_mutex_unlock(&rt_mutex);
|
}
|
||||||
|
rt_cv.notify_one();
|
||||||
|
|
||||||
pthread_join(worker_thread, NULL);
|
worker_thread.join();
|
||||||
|
|
||||||
curl_multi_cleanup(multi);
|
curl_multi_cleanup(multi);
|
||||||
multi = NULL;
|
multi = NULL;
|
||||||
curl_global_cleanup();
|
curl_global_cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
TH_ENTRY_POINT void *RequestManager::RequestManagerHelper(void *obj)
|
|
||||||
{
|
|
||||||
((RequestManager *)obj)->Worker();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RequestManager::Initialise(ByteString Proxy)
|
void RequestManager::Initialise(ByteString Proxy)
|
||||||
{
|
{
|
||||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||||
@@ -64,7 +55,7 @@ namespace http
|
|||||||
|
|
||||||
user_agent = ByteString::Build("PowderToy/", SAVE_VERSION, ".", MINOR_VERSION, " (", IDENT_PLATFORM, "; ", IDENT_BUILD, "; M", MOD_ID, ") TPTPP/", SAVE_VERSION, ".", MINOR_VERSION, ".", BUILD_NUM, IDENT_RELTYPE, ".", SNAPSHOT_ID);
|
user_agent = ByteString::Build("PowderToy/", SAVE_VERSION, ".", MINOR_VERSION, " (", IDENT_PLATFORM, "; ", IDENT_BUILD, "; M", MOD_ID, ") TPTPP/", SAVE_VERSION, ".", MINOR_VERSION, ".", BUILD_NUM, IDENT_RELTYPE, ".", SNAPSHOT_ID);
|
||||||
|
|
||||||
pthread_create(&worker_thread, NULL, &RequestManager::RequestManagerHelper, this);
|
worker_thread = std::thread([this]() { Worker(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestManager::Worker()
|
void RequestManager::Worker()
|
||||||
@@ -72,24 +63,25 @@ namespace http
|
|||||||
bool shutting_down = false;
|
bool shutting_down = false;
|
||||||
while (!shutting_down)
|
while (!shutting_down)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rt_mutex);
|
|
||||||
if (!requests_added_to_multi)
|
|
||||||
{
|
{
|
||||||
while (!rt_shutting_down && requests_to_add.empty() && !requests_to_start && !requests_to_remove)
|
std::unique_lock<std::mutex> l(rt_mutex);
|
||||||
|
if (!requests_added_to_multi)
|
||||||
{
|
{
|
||||||
pthread_cond_wait(&rt_cv, &rt_mutex);
|
while (!rt_shutting_down && requests_to_add.empty() && !requests_to_start && !requests_to_remove)
|
||||||
|
{
|
||||||
|
rt_cv.wait(l);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
shutting_down = rt_shutting_down;
|
||||||
|
requests_to_remove = false;
|
||||||
|
requests_to_start = false;
|
||||||
|
for (Request *request : requests_to_add)
|
||||||
|
{
|
||||||
|
request->status = 0;
|
||||||
|
requests.insert(request);
|
||||||
|
}
|
||||||
|
requests_to_add.clear();
|
||||||
}
|
}
|
||||||
shutting_down = rt_shutting_down;
|
|
||||||
requests_to_remove = false;
|
|
||||||
requests_to_start = false;
|
|
||||||
for (Request *request : requests_to_add)
|
|
||||||
{
|
|
||||||
request->status = 0;
|
|
||||||
requests.insert(request);
|
|
||||||
}
|
|
||||||
requests_to_add.clear();
|
|
||||||
pthread_mutex_unlock(&rt_mutex);
|
|
||||||
|
|
||||||
if (multi && requests_added_to_multi)
|
if (multi && requests_added_to_multi)
|
||||||
{
|
{
|
||||||
@@ -157,52 +149,60 @@ namespace http
|
|||||||
std::set<Request *> requests_to_remove;
|
std::set<Request *> requests_to_remove;
|
||||||
for (Request *request : requests)
|
for (Request *request : requests)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&request->rm_mutex);
|
bool signal_done = false;
|
||||||
if (shutting_down)
|
|
||||||
{
|
{
|
||||||
// In the weird case that a http::Request::Simple* call is
|
std::lock_guard<std::mutex> g(request->rm_mutex);
|
||||||
// waiting on this Request, we should fail the request
|
if (shutting_down)
|
||||||
// instead of cancelling it ourselves.
|
|
||||||
request->status = 610;
|
|
||||||
}
|
|
||||||
if (!request->rm_canceled && request->rm_started && !request->added_to_multi && !request->status)
|
|
||||||
{
|
|
||||||
if (multi && request->easy)
|
|
||||||
{
|
{
|
||||||
MultiAdd(request);
|
// In the weird case that a http::Request::Simple* call is
|
||||||
|
// waiting on this Request, we should fail the request
|
||||||
|
// instead of cancelling it ourselves.
|
||||||
|
request->status = 610;
|
||||||
}
|
}
|
||||||
else
|
if (!request->rm_canceled && request->rm_started && !request->added_to_multi && !request->status)
|
||||||
{
|
{
|
||||||
request->status = 604;
|
if (multi && request->easy)
|
||||||
|
{
|
||||||
|
MultiAdd(request);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
request->status = 604;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (!request->rm_canceled && request->rm_started && !request->rm_finished)
|
||||||
if (!request->rm_canceled && request->rm_started && !request->rm_finished)
|
|
||||||
{
|
|
||||||
if (multi && request->easy)
|
|
||||||
{
|
{
|
||||||
|
if (multi && request->easy)
|
||||||
|
{
|
||||||
#ifdef REQUEST_USE_CURL_OFFSET_T
|
#ifdef REQUEST_USE_CURL_OFFSET_T
|
||||||
curl_easy_getinfo(request->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &request->rm_total);
|
curl_easy_getinfo(request->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD_T, &request->rm_total);
|
||||||
curl_easy_getinfo(request->easy, CURLINFO_SIZE_DOWNLOAD_T, &request->rm_done);
|
curl_easy_getinfo(request->easy, CURLINFO_SIZE_DOWNLOAD_T, &request->rm_done);
|
||||||
#else
|
#else
|
||||||
double total, done;
|
double total, done;
|
||||||
curl_easy_getinfo(request->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &total);
|
curl_easy_getinfo(request->easy, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &total);
|
||||||
curl_easy_getinfo(request->easy, CURLINFO_SIZE_DOWNLOAD, &done);
|
curl_easy_getinfo(request->easy, CURLINFO_SIZE_DOWNLOAD, &done);
|
||||||
request->rm_total = (curl_off_t)total;
|
request->rm_total = (curl_off_t)total;
|
||||||
request->rm_done = (curl_off_t)done;
|
request->rm_done = (curl_off_t)done;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
if (request->status)
|
||||||
|
{
|
||||||
|
request->rm_finished = true;
|
||||||
|
MultiRemove(request);
|
||||||
|
signal_done = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (request->status)
|
if (request->rm_canceled)
|
||||||
{
|
{
|
||||||
request->rm_finished = true;
|
requests_to_remove.insert(request);
|
||||||
MultiRemove(request);
|
|
||||||
pthread_cond_signal(&request->done_cv);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (request->rm_canceled)
|
|
||||||
|
if (signal_done)
|
||||||
{
|
{
|
||||||
requests_to_remove.insert(request);
|
request->done_cv.notify_one();
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&request->rm_mutex);
|
|
||||||
}
|
}
|
||||||
for (Request *request : requests_to_remove)
|
for (Request *request : requests_to_remove)
|
||||||
{
|
{
|
||||||
@@ -235,25 +235,28 @@ namespace http
|
|||||||
|
|
||||||
void RequestManager::AddRequest(Request *request)
|
void RequestManager::AddRequest(Request *request)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rt_mutex);
|
{
|
||||||
requests_to_add.insert(request);
|
std::lock_guard<std::mutex> g(rt_mutex);
|
||||||
pthread_cond_signal(&rt_cv);
|
requests_to_add.insert(request);
|
||||||
pthread_mutex_unlock(&rt_mutex);
|
}
|
||||||
|
rt_cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestManager::StartRequest(Request *request)
|
void RequestManager::StartRequest(Request *request)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rt_mutex);
|
{
|
||||||
requests_to_start = true;
|
std::lock_guard<std::mutex> g(rt_mutex);
|
||||||
pthread_cond_signal(&rt_cv);
|
requests_to_start = true;
|
||||||
pthread_mutex_unlock(&rt_mutex);
|
}
|
||||||
|
rt_cv.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RequestManager::RemoveRequest(Request *request)
|
void RequestManager::RemoveRequest(Request *request)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&rt_mutex);
|
{
|
||||||
requests_to_remove = true;
|
std::lock_guard<std::mutex> g(rt_mutex);
|
||||||
pthread_cond_signal(&rt_cv);
|
requests_to_remove = true;
|
||||||
pthread_mutex_unlock(&rt_mutex);
|
}
|
||||||
|
rt_cv.notify_one();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,20 +2,21 @@
|
|||||||
#define REQUESTMANAGER_H
|
#define REQUESTMANAGER_H
|
||||||
|
|
||||||
#include "common/tpt-minmax.h" // for MSVC, ensures windows.h doesn't cause compile errors by defining min/max
|
#include "common/tpt-minmax.h" // for MSVC, ensures windows.h doesn't cause compile errors by defining min/max
|
||||||
#include "common/tpt-thread.h"
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include "common/Singleton.h"
|
#include "common/Singleton.h"
|
||||||
#include "common/String.h"
|
#include "common/String.h"
|
||||||
#undef GetUserName // pthreads (included by curl) defines this, breaks stuff
|
|
||||||
|
|
||||||
namespace http
|
namespace http
|
||||||
{
|
{
|
||||||
class Request;
|
class Request;
|
||||||
class RequestManager : public Singleton<RequestManager>
|
class RequestManager : public Singleton<RequestManager>
|
||||||
{
|
{
|
||||||
pthread_t worker_thread;
|
std::thread worker_thread;
|
||||||
std::set<Request *> requests;
|
std::set<Request *> requests;
|
||||||
int requests_added_to_multi;
|
int requests_added_to_multi;
|
||||||
|
|
||||||
@@ -23,8 +24,8 @@ namespace http
|
|||||||
bool requests_to_start;
|
bool requests_to_start;
|
||||||
bool requests_to_remove;
|
bool requests_to_remove;
|
||||||
bool rt_shutting_down;
|
bool rt_shutting_down;
|
||||||
pthread_mutex_t rt_mutex;
|
std::mutex rt_mutex;
|
||||||
pthread_cond_t rt_cv;
|
std::condition_variable rt_cv;
|
||||||
|
|
||||||
CURLM *multi;
|
CURLM *multi;
|
||||||
|
|
||||||
@@ -36,8 +37,6 @@ namespace http
|
|||||||
void StartRequest(Request *request);
|
void StartRequest(Request *request);
|
||||||
void RemoveRequest(Request *request);
|
void RemoveRequest(Request *request);
|
||||||
|
|
||||||
static TH_ENTRY_POINT void *RequestManagerHelper(void *obj);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RequestManager();
|
RequestManager();
|
||||||
~RequestManager();
|
~RequestManager();
|
||||||
|
@@ -4,7 +4,6 @@
|
|||||||
#include <limits>
|
#include <limits>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "common/tpt-thread.h"
|
|
||||||
#include "String.h"
|
#include "String.h"
|
||||||
|
|
||||||
ByteString ConversionError::formatError(ByteString::value_type const *at, ByteString::value_type const *upto)
|
ByteString ConversionError::formatError(ByteString::value_type const *at, ByteString::value_type const *upto)
|
||||||
@@ -374,31 +373,10 @@ struct LocaleImpl
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void destroyLocaleImpl(void *ptr)
|
|
||||||
{
|
|
||||||
delete static_cast<LocaleImpl *>(ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pthread_once_t localeOnce = PTHREAD_ONCE_INIT;
|
|
||||||
static pthread_key_t localeKey;
|
|
||||||
|
|
||||||
static void createLocaleKey()
|
|
||||||
{
|
|
||||||
if(int error = pthread_key_create(&localeKey, destroyLocaleImpl))
|
|
||||||
throw std::system_error(error, std::system_category(), "Could not create TLS key for LocaleImpl");
|
|
||||||
}
|
|
||||||
|
|
||||||
static LocaleImpl *getLocaleImpl()
|
static LocaleImpl *getLocaleImpl()
|
||||||
{
|
{
|
||||||
pthread_once(&localeOnce, createLocaleKey);
|
thread_local LocaleImpl li;
|
||||||
void *ptr = pthread_getspecific(localeKey);
|
return &li;
|
||||||
if(!ptr)
|
|
||||||
{
|
|
||||||
ptr = static_cast<void *>(new LocaleImpl());
|
|
||||||
if(int error = pthread_setspecific(localeKey, ptr))
|
|
||||||
throw std::system_error(error, std::system_category(), "Could not put LocaleImpl into TLS");
|
|
||||||
}
|
|
||||||
return static_cast<LocaleImpl *>(ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteString ByteStringBuilder::Build() const
|
ByteString ByteStringBuilder::Build() const
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
#ifndef TPT_THREAD_H
|
|
||||||
#define TPT_THREAD_H
|
|
||||||
|
|
||||||
#if defined(WIN) && defined(__GNUC__)
|
|
||||||
#define TH_ENTRY_POINT __attribute__((force_align_arg_pointer))
|
|
||||||
#define _TIMESPEC_DEFINED
|
|
||||||
#else
|
|
||||||
#define TH_ENTRY_POINT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// fix 'timespec' error in VS 2015
|
|
||||||
#if defined(_MSC_VER) && (_MSC_VER >= 1900)
|
|
||||||
#define _TIMESPEC_DEFINED 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <pthread.h>
|
|
||||||
#undef GetUserName
|
|
||||||
|
|
||||||
// Fix deprecation warnings with recent pthread versions on Windows
|
|
||||||
#if defined(_PTW32_STATIC_LIB) && defined(WIN)
|
|
||||||
#if PTW32_VERSION <= 2, 8, 0, 0
|
|
||||||
#define PTW32_STATIC_LIB
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
@@ -128,9 +128,6 @@ public:
|
|||||||
|
|
||||||
VideoBuffer DumpFrame();
|
VideoBuffer DumpFrame();
|
||||||
|
|
||||||
void Acquire();
|
|
||||||
void Release();
|
|
||||||
|
|
||||||
void blendpixel(int x, int y, int r, int g, int b, int a);
|
void blendpixel(int x, int y, int r, int g, int b, int a);
|
||||||
void addpixel(int x, int y, int r, int g, int b, int a);
|
void addpixel(int x, int y, int r, int g, int b, int a);
|
||||||
|
|
||||||
|
@@ -1,22 +1,12 @@
|
|||||||
#include "Graphics.h"
|
#include "Graphics.h"
|
||||||
#include "FontReader.h"
|
#include "FontReader.h"
|
||||||
#include "common/tpt-thread.h"
|
|
||||||
#ifdef OGLI
|
#ifdef OGLI
|
||||||
|
|
||||||
static pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
//static pthread_mutex_t TMPMUT = PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
Graphics::Graphics():
|
Graphics::Graphics():
|
||||||
sdl_scale(1)
|
sdl_scale(1)
|
||||||
{
|
{
|
||||||
// if(gMutex == TMPMUT)
|
|
||||||
// pthread_mutex_init (&gMutex, NULL);
|
|
||||||
LoadDefaults();
|
LoadDefaults();
|
||||||
InitialiseTextures();
|
InitialiseTextures();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Texture for main UI
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::LoadDefaults()
|
void Graphics::LoadDefaults()
|
||||||
@@ -68,16 +58,6 @@ void Graphics::DestroyTextures()
|
|||||||
//Todo...
|
//Todo...
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::Acquire()
|
|
||||||
{
|
|
||||||
pthread_mutex_lock(&gMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::Release()
|
|
||||||
{
|
|
||||||
pthread_mutex_unlock(&gMutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
Graphics::~Graphics()
|
Graphics::~Graphics()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@@ -9,16 +9,6 @@ sdl_scale(1)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::Acquire()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Graphics::Release()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Graphics::~Graphics()
|
Graphics::~Graphics()
|
||||||
{
|
{
|
||||||
free(vid);
|
free(vid);
|
||||||
|
@@ -225,7 +225,6 @@ void Engine::Draw()
|
|||||||
{
|
{
|
||||||
if(lastBuffer && !(state_ && state_->Position.X == 0 && state_->Position.Y == 0 && state_->Size.X == width_ && state_->Size.Y == height_))
|
if(lastBuffer && !(state_ && state_->Position.X == 0 && state_->Position.Y == 0 && state_->Size.X == width_ && state_->Size.Y == height_))
|
||||||
{
|
{
|
||||||
g->Acquire();
|
|
||||||
g->Clear();
|
g->Clear();
|
||||||
#ifndef OGLI
|
#ifndef OGLI
|
||||||
memcpy(g->vid, lastBuffer, (width_ * height_) * PIXELSIZE);
|
memcpy(g->vid, lastBuffer, (width_ * height_) * PIXELSIZE);
|
||||||
@@ -242,7 +241,6 @@ void Engine::Draw()
|
|||||||
state_->DoDraw();
|
state_->DoDraw();
|
||||||
|
|
||||||
g->Finalise();
|
g->Finalise();
|
||||||
g->Release();
|
|
||||||
FrameIndex++;
|
FrameIndex++;
|
||||||
FrameIndex %= 7200;
|
FrameIndex %= 7200;
|
||||||
}
|
}
|
||||||
|
@@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "client/Client.h"
|
#include "client/Client.h"
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
SearchModel::SearchModel():
|
SearchModel::SearchModel():
|
||||||
loadedSave(NULL),
|
loadedSave(NULL),
|
||||||
currentSort("best"),
|
currentSort("best"),
|
||||||
@@ -14,8 +16,10 @@ SearchModel::SearchModel():
|
|||||||
saveListLoaded(false),
|
saveListLoaded(false),
|
||||||
updateSaveListWorking(false),
|
updateSaveListWorking(false),
|
||||||
updateSaveListFinished(false),
|
updateSaveListFinished(false),
|
||||||
|
updateSaveListResult(nullptr),
|
||||||
updateTagListWorking(false),
|
updateTagListWorking(false),
|
||||||
updateTagListFinished(false)
|
updateTagListFinished(false),
|
||||||
|
updateTagListResult(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,36 +33,26 @@ bool SearchModel::GetShowTags()
|
|||||||
return showTags;
|
return showTags;
|
||||||
}
|
}
|
||||||
|
|
||||||
TH_ENTRY_POINT void * SearchModel::updateSaveListTHelper(void * obj)
|
void SearchModel::updateSaveListT()
|
||||||
{
|
|
||||||
return ((SearchModel *)obj)->updateSaveListT();
|
|
||||||
}
|
|
||||||
|
|
||||||
void * SearchModel::updateSaveListT()
|
|
||||||
{
|
{
|
||||||
ByteString category = "";
|
ByteString category = "";
|
||||||
if(showFavourite)
|
if(showFavourite)
|
||||||
category = "Favourites";
|
category = "Favourites";
|
||||||
if(showOwn && Client::Ref().GetAuthUser().UserID)
|
if(showOwn && Client::Ref().GetAuthUser().UserID)
|
||||||
category = "by:"+Client::Ref().GetAuthUser().Username;
|
category = "by:"+Client::Ref().GetAuthUser().Username;
|
||||||
vector<SaveInfo*> * saveList = Client::Ref().SearchSaves((currentPage-1)*20, 20, lastQuery, currentSort=="new"?"date":"votes", category, thResultCount);
|
std::vector<SaveInfo*> * saveList = Client::Ref().SearchSaves((currentPage-1)*20, 20, lastQuery, currentSort=="new"?"date":"votes", category, thResultCount);
|
||||||
|
|
||||||
|
updateSaveListResult = saveList;
|
||||||
updateSaveListFinished = true;
|
updateSaveListFinished = true;
|
||||||
return saveList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TH_ENTRY_POINT void * SearchModel::updateTagListTHelper(void * obj)
|
void SearchModel::updateTagListT()
|
||||||
{
|
|
||||||
return ((SearchModel *)obj)->updateTagListT();
|
|
||||||
}
|
|
||||||
|
|
||||||
void * SearchModel::updateTagListT()
|
|
||||||
{
|
{
|
||||||
int tagResultCount;
|
int tagResultCount;
|
||||||
std::vector<std::pair<ByteString, int> > * tagList = Client::Ref().GetTags(0, 24, "", tagResultCount);
|
std::vector<std::pair<ByteString, int> > * tagList = Client::Ref().GetTags(0, 24, "", tagResultCount);
|
||||||
|
|
||||||
|
updateTagListResult = tagList;
|
||||||
updateTagListFinished = true;
|
updateTagListFinished = true;
|
||||||
return tagList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SearchModel::UpdateSaveList(int pageNumber, String query)
|
bool SearchModel::UpdateSaveList(int pageNumber, String query)
|
||||||
@@ -88,12 +82,12 @@ bool SearchModel::UpdateSaveList(int pageNumber, String query)
|
|||||||
{
|
{
|
||||||
updateTagListFinished = false;
|
updateTagListFinished = false;
|
||||||
updateTagListWorking = true;
|
updateTagListWorking = true;
|
||||||
pthread_create(&updateTagListThread, 0, &SearchModel::updateTagListTHelper, this);
|
std::thread([this]() { updateTagListT(); }).detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSaveListFinished = false;
|
updateSaveListFinished = false;
|
||||||
updateSaveListWorking = true;
|
updateSaveListWorking = true;
|
||||||
pthread_create(&updateSaveListThread, 0, &SearchModel::updateSaveListTHelper, this);
|
std::thread([this]() { updateSaveListT(); }).detach();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -117,12 +111,12 @@ SaveInfo * SearchModel::GetLoadedSave(){
|
|||||||
return loadedSave;
|
return loadedSave;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<SaveInfo*> SearchModel::GetSaveList()
|
std::vector<SaveInfo*> SearchModel::GetSaveList()
|
||||||
{
|
{
|
||||||
return saveList;
|
return saveList;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<pair<ByteString, int> > SearchModel::GetTagList()
|
std::vector<std::pair<ByteString, int> > SearchModel::GetTagList()
|
||||||
{
|
{
|
||||||
return tagList;
|
return tagList;
|
||||||
}
|
}
|
||||||
@@ -137,8 +131,8 @@ void SearchModel::Update()
|
|||||||
lastError = "";
|
lastError = "";
|
||||||
saveListLoaded = true;
|
saveListLoaded = true;
|
||||||
|
|
||||||
vector<SaveInfo*> * tempSaveList;
|
std::vector<SaveInfo *> *tempSaveList = updateSaveListResult;
|
||||||
pthread_join(updateSaveListThread, (void**)&tempSaveList);
|
updateSaveListResult = nullptr;
|
||||||
|
|
||||||
if(tempSaveList)
|
if(tempSaveList)
|
||||||
{
|
{
|
||||||
@@ -164,8 +158,8 @@ void SearchModel::Update()
|
|||||||
{
|
{
|
||||||
updateTagListWorking = false;
|
updateTagListWorking = false;
|
||||||
|
|
||||||
vector<pair<ByteString, int> > * tempTagList;
|
std::vector<std::pair<ByteString, int>> *tempTagList = updateTagListResult;
|
||||||
pthread_join(updateTagListThread, (void**)&tempTagList);
|
updateTagListResult = nullptr;
|
||||||
|
|
||||||
if(tempTagList)
|
if(tempTagList)
|
||||||
{
|
{
|
||||||
|
@@ -4,13 +4,11 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/String.h"
|
#include "common/String.h"
|
||||||
#include "common/tpt-minmax.h"
|
#include "common/tpt-minmax.h"
|
||||||
#include "common/tpt-thread.h"
|
#include <atomic>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include "client/SaveInfo.h"
|
#include "client/SaveInfo.h"
|
||||||
#include "SearchView.h"
|
#include "SearchView.h"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
class SearchView;
|
class SearchView;
|
||||||
class SearchModel
|
class SearchModel
|
||||||
{
|
{
|
||||||
@@ -19,10 +17,10 @@ private:
|
|||||||
ByteString currentSort;
|
ByteString currentSort;
|
||||||
String lastQuery;
|
String lastQuery;
|
||||||
String lastError;
|
String lastError;
|
||||||
vector<int> selected;
|
std::vector<int> selected;
|
||||||
vector<SearchView*> observers;
|
std::vector<SearchView*> observers;
|
||||||
vector<SaveInfo*> saveList;
|
std::vector<SaveInfo*> saveList;
|
||||||
vector<pair<ByteString, int> > tagList;
|
std::vector<std::pair<ByteString, int> > tagList;
|
||||||
int currentPage;
|
int currentPage;
|
||||||
int resultCount;
|
int resultCount;
|
||||||
int thResultCount;
|
int thResultCount;
|
||||||
@@ -40,16 +38,14 @@ private:
|
|||||||
//Variables and methods for background save request
|
//Variables and methods for background save request
|
||||||
bool saveListLoaded;
|
bool saveListLoaded;
|
||||||
bool updateSaveListWorking;
|
bool updateSaveListWorking;
|
||||||
volatile bool updateSaveListFinished;
|
std::atomic<bool> updateSaveListFinished;
|
||||||
pthread_t updateSaveListThread;
|
void updateSaveListT();
|
||||||
TH_ENTRY_POINT static void * updateSaveListTHelper(void * obj);
|
std::vector<SaveInfo *> *updateSaveListResult;
|
||||||
void * updateSaveListT();
|
|
||||||
|
|
||||||
bool updateTagListWorking;
|
bool updateTagListWorking;
|
||||||
volatile bool updateTagListFinished;
|
std::atomic<bool> updateTagListFinished;
|
||||||
pthread_t updateTagListThread;
|
void updateTagListT();
|
||||||
TH_ENTRY_POINT static void * updateTagListTHelper(void * obj);
|
std::vector<std::pair<ByteString, int>> *updateTagListResult;
|
||||||
void * updateTagListT();
|
|
||||||
public:
|
public:
|
||||||
SearchModel();
|
SearchModel();
|
||||||
virtual ~SearchModel();
|
virtual ~SearchModel();
|
||||||
@@ -58,8 +54,8 @@ public:
|
|||||||
bool GetShowTags();
|
bool GetShowTags();
|
||||||
void AddObserver(SearchView * observer);
|
void AddObserver(SearchView * observer);
|
||||||
bool UpdateSaveList(int pageNumber, String query);
|
bool UpdateSaveList(int pageNumber, String query);
|
||||||
vector<SaveInfo*> GetSaveList();
|
std::vector<SaveInfo*> GetSaveList();
|
||||||
vector<pair<ByteString, int> > GetTagList();
|
std::vector<std::pair<ByteString, int> > GetTagList();
|
||||||
String GetLastError() { return lastError; }
|
String GetLastError() { return lastError; }
|
||||||
int GetPageCount()
|
int GetPageCount()
|
||||||
{
|
{
|
||||||
@@ -79,7 +75,7 @@ public:
|
|||||||
void SetLoadedSave(SaveInfo * save);
|
void SetLoadedSave(SaveInfo * save);
|
||||||
SaveInfo * GetLoadedSave();
|
SaveInfo * GetLoadedSave();
|
||||||
bool GetSavesLoaded() { return saveListLoaded; }
|
bool GetSavesLoaded() { return saveListLoaded; }
|
||||||
vector<int> GetSelected() { return selected; }
|
std::vector<int> GetSelected() { return selected; }
|
||||||
void ClearSelected() { selected.clear(); notifySelectedChanged(); }
|
void ClearSelected() { selected.clear(); notifySelectedChanged(); }
|
||||||
void SelectSave(int saveID);
|
void SelectSave(int saveID);
|
||||||
void DeselectSave(int saveID);
|
void DeselectSave(int saveID);
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include "common/tpt-thread.h"
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Gravity.h"
|
#include "Gravity.h"
|
||||||
#include "Misc.h"
|
#include "Misc.h"
|
||||||
@@ -85,13 +84,15 @@ void Gravity::gravity_update_async()
|
|||||||
int result;
|
int result;
|
||||||
if (ngrav_enable)
|
if (ngrav_enable)
|
||||||
{
|
{
|
||||||
if (!pthread_mutex_trylock(&gravmutex))
|
bool signal_grav = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
result = grav_ready;
|
std::unique_lock<std::mutex> l(gravmutex, std::defer_lock);
|
||||||
if (result) //Did the gravity thread finish?
|
if (l.try_lock())
|
||||||
{
|
{
|
||||||
//if (!sys_pause||framerender){ //Only update if not paused
|
result = grav_ready;
|
||||||
//Switch the full size gravmaps, we don't really need the two above any more
|
if (result) //Did the gravity thread finish?
|
||||||
|
{
|
||||||
float *tmpf;
|
float *tmpf;
|
||||||
|
|
||||||
if (th_gravchanged && !ignoreNextResult)
|
if (th_gravchanged && !ignoreNextResult)
|
||||||
@@ -121,10 +122,14 @@ void Gravity::gravity_update_async()
|
|||||||
th_gravmap = tmpf;
|
th_gravmap = tmpf;
|
||||||
|
|
||||||
grav_ready = 0; //Tell the other thread that we're ready for it to continue
|
grav_ready = 0; //Tell the other thread that we're ready for it to continue
|
||||||
pthread_cond_signal(&gravcv);
|
signal_grav = true;
|
||||||
//}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signal_grav)
|
||||||
|
{
|
||||||
|
gravcv.notify_one();
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&gravmutex);
|
|
||||||
}
|
}
|
||||||
//Apply the gravity mask
|
//Apply the gravity mask
|
||||||
membwand(gravy, gravmask, (XRES/CELL)*(YRES/CELL)*sizeof(float), (XRES/CELL)*(YRES/CELL)*sizeof(unsigned));
|
membwand(gravy, gravmask, (XRES/CELL)*(YRES/CELL)*sizeof(float), (XRES/CELL)*(YRES/CELL)*sizeof(unsigned));
|
||||||
@@ -133,12 +138,6 @@ void Gravity::gravity_update_async()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TH_ENTRY_POINT void *Gravity::update_grav_async_helper(void * context)
|
|
||||||
{
|
|
||||||
((Gravity *)context)->update_grav_async();
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Gravity::update_grav_async()
|
void Gravity::update_grav_async()
|
||||||
{
|
{
|
||||||
int done = 0;
|
int done = 0;
|
||||||
@@ -155,7 +154,8 @@ void Gravity::update_grav_async()
|
|||||||
if (!grav_fft_status)
|
if (!grav_fft_status)
|
||||||
grav_fft_init();
|
grav_fft_init();
|
||||||
#endif
|
#endif
|
||||||
pthread_mutex_lock(&gravmutex);
|
|
||||||
|
std::unique_lock<std::mutex> l(gravmutex);
|
||||||
while (!thread_done)
|
while (!thread_done)
|
||||||
{
|
{
|
||||||
if (!done)
|
if (!done)
|
||||||
@@ -167,13 +167,11 @@ void Gravity::update_grav_async()
|
|||||||
thread_done = gravthread_done;
|
thread_done = gravthread_done;
|
||||||
} else {
|
} else {
|
||||||
// wait for main thread
|
// wait for main thread
|
||||||
pthread_cond_wait(&gravcv, &gravmutex);
|
gravcv.wait(l);
|
||||||
done = grav_ready;
|
done = grav_ready;
|
||||||
thread_done = gravthread_done;
|
thread_done = gravthread_done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&gravmutex);
|
|
||||||
pthread_exit(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gravity::start_grav_async()
|
void Gravity::start_grav_async()
|
||||||
@@ -183,9 +181,7 @@ void Gravity::start_grav_async()
|
|||||||
|
|
||||||
gravthread_done = 0;
|
gravthread_done = 0;
|
||||||
grav_ready = 0;
|
grav_ready = 0;
|
||||||
pthread_mutex_init (&gravmutex, NULL);
|
gravthread = std::thread([this]() { update_grav_async(); }); //Start asynchronous gravity simulation
|
||||||
pthread_cond_init(&gravcv, NULL);
|
|
||||||
pthread_create(&gravthread, NULL, &Gravity::update_grav_async_helper, this); //Start asynchronous gravity simulation
|
|
||||||
ngrav_enable = 1;
|
ngrav_enable = 1;
|
||||||
|
|
||||||
memset(gravy, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float));
|
memset(gravy, 0, (XRES/CELL)*(YRES/CELL)*sizeof(float));
|
||||||
@@ -198,12 +194,12 @@ void Gravity::stop_grav_async()
|
|||||||
{
|
{
|
||||||
if (ngrav_enable)
|
if (ngrav_enable)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&gravmutex);
|
{
|
||||||
gravthread_done = 1;
|
std::lock_guard<std::mutex> g(gravmutex);
|
||||||
pthread_cond_signal(&gravcv);
|
gravthread_done = 1;
|
||||||
pthread_mutex_unlock(&gravmutex);
|
}
|
||||||
pthread_join(gravthread, NULL);
|
gravcv.notify_one();
|
||||||
pthread_mutex_destroy(&gravmutex); //Destroy the mutex
|
gravthread.join();
|
||||||
ngrav_enable = 0;
|
ngrav_enable = 0;
|
||||||
}
|
}
|
||||||
//Clear the grav velocities
|
//Clear the grav velocities
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
#ifndef GRAVITY_H
|
#ifndef GRAVITY_H
|
||||||
#define GRAVITY_H
|
#define GRAVITY_H
|
||||||
|
|
||||||
#include "common/tpt-thread.h"
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <condition_variable>
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Simulation.h"
|
#include "Simulation.h"
|
||||||
|
|
||||||
@@ -18,28 +20,6 @@ struct mask_el {
|
|||||||
};
|
};
|
||||||
typedef struct mask_el mask_el;
|
typedef struct mask_el mask_el;
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* float *gravmap = NULL;//Maps to be used by the main thread
|
|
||||||
float *gravp = NULL;
|
|
||||||
float *gravy = NULL;
|
|
||||||
float *gravx = NULL;
|
|
||||||
unsigned *gravmask = NULL;
|
|
||||||
|
|
||||||
float *th_ogravmap = NULL;// Maps to be processed by the gravity thread
|
|
||||||
float *th_gravmap = NULL;
|
|
||||||
float *th_gravx = NULL;
|
|
||||||
float *th_gravy = NULL;
|
|
||||||
float *th_gravp = NULL;
|
|
||||||
|
|
||||||
int th_gravchanged = 0;
|
|
||||||
|
|
||||||
pthread_t gravthread;
|
|
||||||
pthread_mutex_t gravmutex;
|
|
||||||
pthread_cond_t gravcv;
|
|
||||||
int grav_ready = 0;
|
|
||||||
int gravthread_done = 0;
|
|
||||||
*/
|
|
||||||
class Gravity
|
class Gravity
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@@ -52,9 +32,9 @@ private:
|
|||||||
|
|
||||||
int th_gravchanged;
|
int th_gravchanged;
|
||||||
|
|
||||||
pthread_t gravthread;
|
std::thread gravthread;
|
||||||
pthread_mutex_t gravmutex;
|
std::mutex gravmutex;
|
||||||
pthread_cond_t gravcv;
|
std::condition_variable gravcv;
|
||||||
int grav_ready;
|
int grav_ready;
|
||||||
int gravthread_done;
|
int gravthread_done;
|
||||||
|
|
||||||
@@ -84,7 +64,6 @@ public:
|
|||||||
void gravity_cleanup();
|
void gravity_cleanup();
|
||||||
void gravity_update_async();
|
void gravity_update_async();
|
||||||
|
|
||||||
TH_ENTRY_POINT static void *update_grav_async_helper(void * context);
|
|
||||||
void update_grav_async();
|
void update_grav_async();
|
||||||
|
|
||||||
void start_grav_async();
|
void start_grav_async();
|
||||||
|
@@ -29,13 +29,11 @@ SaveRenderer::SaveRenderer(){
|
|||||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Reset framebuffer binding
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); // Reset framebuffer binding
|
||||||
glDisable(GL_TEXTURE_2D);
|
glDisable(GL_TEXTURE_2D);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pthread_mutex_init(&renderMutex, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire)
|
VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&renderMutex);
|
std::lock_guard<std::mutex> gx(renderMutex);
|
||||||
|
|
||||||
int width, height;
|
int width, height;
|
||||||
VideoBuffer * tempThumb = NULL;
|
VideoBuffer * tempThumb = NULL;
|
||||||
@@ -43,7 +41,6 @@ VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire)
|
|||||||
height = save->blockHeight;
|
height = save->blockHeight;
|
||||||
bool doCollapse = save->Collapsed();
|
bool doCollapse = save->Collapsed();
|
||||||
|
|
||||||
g->Acquire();
|
|
||||||
g->Clear();
|
g->Clear();
|
||||||
sim->clear_sim();
|
sim->clear_sim();
|
||||||
|
|
||||||
@@ -148,15 +145,13 @@ VideoBuffer * SaveRenderer::Render(GameSave * save, bool decorations, bool fire)
|
|||||||
}
|
}
|
||||||
if(doCollapse)
|
if(doCollapse)
|
||||||
save->Collapse();
|
save->Collapse();
|
||||||
g->Release();
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&renderMutex);
|
|
||||||
return tempThumb;
|
return tempThumb;
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoBuffer * SaveRenderer::Render(unsigned char * saveData, int dataSize, bool decorations, bool fire)
|
VideoBuffer * SaveRenderer::Render(unsigned char * saveData, int dataSize, bool decorations, bool fire)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&renderMutex);
|
std::lock_guard<std::mutex> g(renderMutex);
|
||||||
|
|
||||||
GameSave * tempSave;
|
GameSave * tempSave;
|
||||||
try {
|
try {
|
||||||
@@ -167,17 +162,15 @@ VideoBuffer * SaveRenderer::Render(unsigned char * saveData, int dataSize, bool
|
|||||||
VideoBuffer * buffer = new VideoBuffer(64, 64);
|
VideoBuffer * buffer = new VideoBuffer(64, 64);
|
||||||
buffer->BlendCharacter(32, 32, 'x', 255, 255, 255, 255);
|
buffer->BlendCharacter(32, 32, 'x', 255, 255, 255, 255);
|
||||||
|
|
||||||
pthread_mutex_unlock(&renderMutex);
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
VideoBuffer * thumb = Render(tempSave, decorations, fire);
|
VideoBuffer * thumb = Render(tempSave, decorations, fire);
|
||||||
delete tempSave;
|
delete tempSave;
|
||||||
|
|
||||||
pthread_mutex_unlock(&renderMutex);
|
|
||||||
return thumb;
|
return thumb;
|
||||||
}
|
}
|
||||||
|
|
||||||
SaveRenderer::~SaveRenderer() {
|
SaveRenderer::~SaveRenderer()
|
||||||
pthread_mutex_destroy(&renderMutex);
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
#include "graphics/OpenGLHeaders.h"
|
#include "graphics/OpenGLHeaders.h"
|
||||||
#endif
|
#endif
|
||||||
#include "common/Singleton.h"
|
#include "common/Singleton.h"
|
||||||
#include "common/tpt-thread.h"
|
#include <mutex>
|
||||||
|
|
||||||
class GameSave;
|
class GameSave;
|
||||||
class VideoBuffer;
|
class VideoBuffer;
|
||||||
@@ -16,7 +16,7 @@ class SaveRenderer: public Singleton<SaveRenderer> {
|
|||||||
Graphics * g;
|
Graphics * g;
|
||||||
Simulation * sim;
|
Simulation * sim;
|
||||||
Renderer * ren;
|
Renderer * ren;
|
||||||
pthread_mutex_t renderMutex;
|
std::mutex renderMutex;
|
||||||
public:
|
public:
|
||||||
SaveRenderer();
|
SaveRenderer();
|
||||||
VideoBuffer * Render(GameSave * save, bool decorations = true, bool fire = true);
|
VideoBuffer * Render(GameSave * save, bool decorations = true, bool fire = true);
|
||||||
|
@@ -5,11 +5,13 @@
|
|||||||
void AbandonableTask::doWork_wrapper()
|
void AbandonableTask::doWork_wrapper()
|
||||||
{
|
{
|
||||||
Task::doWork_wrapper();
|
Task::doWork_wrapper();
|
||||||
pthread_cond_signal(&done_cv);
|
done_cv.notify_one();
|
||||||
|
|
||||||
pthread_mutex_lock(&taskMutex);
|
bool abandoned;
|
||||||
bool abandoned = thAbandoned;
|
{
|
||||||
pthread_mutex_unlock(&taskMutex);
|
std::lock_guard<std::mutex> g(taskMutex);
|
||||||
|
abandoned = thAbandoned;
|
||||||
|
}
|
||||||
if (abandoned)
|
if (abandoned)
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
@@ -18,12 +20,10 @@ void AbandonableTask::doWork_wrapper()
|
|||||||
|
|
||||||
void AbandonableTask::Finish()
|
void AbandonableTask::Finish()
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&taskMutex);
|
|
||||||
while (!thDone)
|
|
||||||
{
|
{
|
||||||
pthread_cond_wait(&done_cv, &taskMutex);
|
std::unique_lock<std::mutex> l(taskMutex);
|
||||||
|
done_cv.wait(l, [this]() { return thDone; });
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&taskMutex);
|
|
||||||
|
|
||||||
// Poll to make sure that the rest of the Task knows that it's
|
// Poll to make sure that the rest of the Task knows that it's
|
||||||
// done, not just us. This has to be done because the thread that started
|
// done, not just us. This has to be done because the thread that started
|
||||||
@@ -37,23 +37,24 @@ void AbandonableTask::Finish()
|
|||||||
void AbandonableTask::Abandon()
|
void AbandonableTask::Abandon()
|
||||||
{
|
{
|
||||||
bool delete_this = false;
|
bool delete_this = false;
|
||||||
pthread_mutex_lock(&taskMutex);
|
|
||||||
if (thDone)
|
|
||||||
{
|
{
|
||||||
// If thDone is true, the thread has already finished. We're
|
std::lock_guard<std::mutex> g(taskMutex);
|
||||||
// not calling Poll because it may call callbacks, which
|
if (thDone)
|
||||||
// an abandoned task shouldn't do. Instead we just delete the
|
{
|
||||||
// AbandonableTask after unlocking the mutex.
|
// If thDone is true, the thread has already finished. We're
|
||||||
delete_this = true;
|
// not calling Poll because it may call callbacks, which
|
||||||
|
// an abandoned task shouldn't do. Instead we just delete the
|
||||||
|
// AbandonableTask after unlocking the mutex.
|
||||||
|
delete_this = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If at this point thDone is still false, the thread is still
|
||||||
|
// running, meaning we can safely set thAbandoned and let
|
||||||
|
// AbandonableTask::doWork_wrapper delete the AbandonableTask later.
|
||||||
|
thAbandoned = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// If at this point thDone is still false, the thread is still
|
|
||||||
// running, meaning we can safely set thAbandoned and let
|
|
||||||
// AbandonableTask::doWork_wrapper delete the AbandonableTask later.
|
|
||||||
thAbandoned = true;
|
|
||||||
}
|
|
||||||
pthread_mutex_unlock(&taskMutex);
|
|
||||||
|
|
||||||
if (delete_this)
|
if (delete_this)
|
||||||
{
|
{
|
||||||
@@ -64,11 +65,9 @@ void AbandonableTask::Abandon()
|
|||||||
AbandonableTask::AbandonableTask() :
|
AbandonableTask::AbandonableTask() :
|
||||||
thAbandoned(false)
|
thAbandoned(false)
|
||||||
{
|
{
|
||||||
pthread_cond_init(&done_cv, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AbandonableTask::~AbandonableTask()
|
AbandonableTask::~AbandonableTask()
|
||||||
{
|
{
|
||||||
pthread_cond_destroy(&done_cv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,9 +3,11 @@
|
|||||||
|
|
||||||
#include "Task.h"
|
#include "Task.h"
|
||||||
|
|
||||||
|
#include <condition_variable>
|
||||||
|
|
||||||
class AbandonableTask : public Task
|
class AbandonableTask : public Task
|
||||||
{
|
{
|
||||||
pthread_cond_t done_cv;
|
std::condition_variable done_cv;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Finish();
|
void Finish();
|
||||||
|
@@ -12,10 +12,7 @@ void Task::AddTaskListener(TaskListener * listener)
|
|||||||
void Task::Start()
|
void Task::Start()
|
||||||
{
|
{
|
||||||
before();
|
before();
|
||||||
// This would use a lambda if we didn't use pthreads and if I dared omit
|
std::thread([this]() { doWork_wrapper(); }).detach();
|
||||||
// the TH_ENTRY_POINT from the function type.
|
|
||||||
pthread_create(&doWorkThread, 0, &Task::doWork_helper, this);
|
|
||||||
pthread_detach(doWorkThread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Task::GetProgress()
|
int Task::GetProgress()
|
||||||
@@ -52,13 +49,14 @@ void Task::Poll()
|
|||||||
bool newSuccess = false;
|
bool newSuccess = false;
|
||||||
String newStatus;
|
String newStatus;
|
||||||
String newError;
|
String newError;
|
||||||
pthread_mutex_lock(&taskMutex);
|
{
|
||||||
newProgress = thProgress;
|
std::lock_guard<std::mutex> g(taskMutex);
|
||||||
newDone = thDone;
|
newProgress = thProgress;
|
||||||
newSuccess = thSuccess;
|
newDone = thDone;
|
||||||
newStatus = thStatus;
|
newSuccess = thSuccess;
|
||||||
newError = thError;
|
newStatus = thStatus;
|
||||||
pthread_mutex_unlock(&taskMutex);
|
newError = thError;
|
||||||
|
}
|
||||||
|
|
||||||
success = newSuccess;
|
success = newSuccess;
|
||||||
|
|
||||||
@@ -93,12 +91,10 @@ Task::Task() :
|
|||||||
thDone(false),
|
thDone(false),
|
||||||
listener(NULL)
|
listener(NULL)
|
||||||
{
|
{
|
||||||
pthread_mutex_init(&taskMutex, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Task::~Task()
|
Task::~Task()
|
||||||
{
|
{
|
||||||
pthread_mutex_destroy(&taskMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::before()
|
void Task::before()
|
||||||
@@ -124,37 +120,29 @@ void Task::after()
|
|||||||
void Task::doWork_wrapper()
|
void Task::doWork_wrapper()
|
||||||
{
|
{
|
||||||
bool newSuccess = doWork();
|
bool newSuccess = doWork();
|
||||||
pthread_mutex_lock(&taskMutex);
|
{
|
||||||
thSuccess = newSuccess;
|
std::lock_guard<std::mutex> g(taskMutex);
|
||||||
thDone = true;
|
thSuccess = newSuccess;
|
||||||
pthread_mutex_unlock(&taskMutex);
|
thDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TH_ENTRY_POINT void *Task::doWork_helper(void *ref)
|
|
||||||
{
|
|
||||||
((Task *)ref)->doWork_wrapper();
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::notifyProgress(int progress)
|
void Task::notifyProgress(int progress)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&taskMutex);
|
std::lock_guard<std::mutex> g(taskMutex);
|
||||||
thProgress = progress;
|
thProgress = progress;
|
||||||
pthread_mutex_unlock(&taskMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::notifyStatus(String status)
|
void Task::notifyStatus(String status)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&taskMutex);
|
std::lock_guard<std::mutex> g(taskMutex);
|
||||||
thStatus = status;
|
thStatus = status;
|
||||||
pthread_mutex_unlock(&taskMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::notifyError(String error)
|
void Task::notifyError(String error)
|
||||||
{
|
{
|
||||||
pthread_mutex_lock(&taskMutex);
|
std::lock_guard<std::mutex> g(taskMutex);
|
||||||
thError = error;
|
thError = error;
|
||||||
pthread_mutex_unlock(&taskMutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Task::notifyProgressMain()
|
void Task::notifyProgressMain()
|
||||||
|
@@ -2,9 +2,10 @@
|
|||||||
#define TASK_H_
|
#define TASK_H_
|
||||||
|
|
||||||
#include "common/String.h"
|
#include "common/String.h"
|
||||||
#include "common/tpt-thread.h"
|
|
||||||
#include "TaskListener.h"
|
#include "TaskListener.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
class TaskListener;
|
class TaskListener;
|
||||||
class Task {
|
class Task {
|
||||||
@@ -19,6 +20,7 @@ public:
|
|||||||
virtual void Poll();
|
virtual void Poll();
|
||||||
Task();
|
Task();
|
||||||
virtual ~Task();
|
virtual ~Task();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
int progress;
|
int progress;
|
||||||
bool done;
|
bool done;
|
||||||
@@ -32,16 +34,13 @@ protected:
|
|||||||
String thStatus;
|
String thStatus;
|
||||||
String thError;
|
String thError;
|
||||||
|
|
||||||
TaskListener * listener;
|
TaskListener *listener;
|
||||||
pthread_t doWorkThread;
|
std::mutex taskMutex;
|
||||||
pthread_mutex_t taskMutex;
|
|
||||||
|
|
||||||
|
|
||||||
virtual void before();
|
virtual void before();
|
||||||
virtual void after();
|
virtual void after();
|
||||||
virtual bool doWork();
|
virtual bool doWork();
|
||||||
virtual void doWork_wrapper();
|
virtual void doWork_wrapper();
|
||||||
TH_ENTRY_POINT static void * doWork_helper(void * ref);
|
|
||||||
|
|
||||||
virtual void notifyProgress(int progress);
|
virtual void notifyProgress(int progress);
|
||||||
virtual void notifyError(String error);
|
virtual void notifyError(String error);
|
||||||
|
Reference in New Issue
Block a user