@@ -1,11 +1,13 @@ | |||||
// | // | ||||
// Lol Engine - Fractal tutorial | |||||
// Lol Engine - Fractal tutorial | |||||
// | // | ||||
// Copyright: (c) 2011-2013 Sam Hocevar <sam@hocevar.net> | |||||
// This program is free software; you can redistribute it and/or | |||||
// modify it under the terms of the Do What The Fuck You Want To | |||||
// Public License, Version 2, as published by Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// Copyright © 2011—2015 Sam Hocevar <sam@hocevar.net> | |||||
// | |||||
// This program is free software. It comes without any warranty, to | |||||
// the extent permitted by applicable law. You can redistribute it | |||||
// and/or modify it under the terms of the Do What the Fuck You Want | |||||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||||
// See http://www.wtfpl.net/ for more details. | |||||
// | // | ||||
#if HAVE_CONFIG_H | #if HAVE_CONFIG_H | ||||
@@ -125,9 +127,9 @@ public: | |||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
/* Spawn worker threads and wait for their readiness. */ | /* Spawn worker threads and wait for their readiness. */ | ||||
for (int i = 0; i < MAX_THREADS; i++) | for (int i = 0; i < MAX_THREADS; i++) | ||||
m_threads[i] = new Thread(DoWorkHelper, this); | |||||
m_threads[i] = new thread(std::bind(&Fractal::DoWorkHelper, this)); | |||||
for (int i = 0; i < MAX_THREADS; i++) | for (int i = 0; i < MAX_THREADS; i++) | ||||
m_spawnqueue.Pop(); | |||||
m_spawnqueue.pop(); | |||||
#endif | #endif | ||||
} | } | ||||
@@ -137,9 +139,9 @@ public: | |||||
/* Signal worker threads for completion and wait for | /* Signal worker threads for completion and wait for | ||||
* them to quit. */ | * them to quit. */ | ||||
for (int i = 0; i < MAX_THREADS; i++) | for (int i = 0; i < MAX_THREADS; i++) | ||||
m_jobqueue.Push(-1); | |||||
m_jobqueue.push(-1); | |||||
for (int i = 0; i < MAX_THREADS; i++) | for (int i = 0; i < MAX_THREADS; i++) | ||||
m_donequeue.Pop(); | |||||
m_donequeue.pop(); | |||||
#endif | #endif | ||||
//Input::UntrackMouse(this); | //Input::UntrackMouse(this); | ||||
@@ -310,7 +312,7 @@ public: | |||||
for (int i = 0; i < m_size.y; i += MAX_LINES * 2) | for (int i = 0; i < m_size.y; i += MAX_LINES * 2) | ||||
{ | { | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
m_jobqueue.Push(i); | |||||
m_jobqueue.push(i); | |||||
#else | #else | ||||
DoWork(i); | DoWork(i); | ||||
#endif | #endif | ||||
@@ -319,20 +321,18 @@ public: | |||||
} | } | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
static void *DoWorkHelper(void *data) | |||||
void DoWorkHelper() | |||||
{ | { | ||||
Fractal *that = (Fractal *)data; | |||||
that->m_spawnqueue.Push(0); | |||||
m_spawnqueue.push(0); | |||||
for ( ; ; ) | for ( ; ; ) | ||||
{ | { | ||||
int line = that->m_jobqueue.Pop(); | |||||
int line = m_jobqueue.pop(); | |||||
if (line == -1) | if (line == -1) | ||||
break; | break; | ||||
that->DoWork(line); | |||||
that->m_donequeue.Push(0); | |||||
DoWork(line); | |||||
m_donequeue.push(0); | |||||
} | } | ||||
that->m_donequeue.Push(0); | |||||
return NULL; | |||||
m_donequeue.push(0); | |||||
}; | }; | ||||
#endif | #endif | ||||
@@ -497,7 +497,7 @@ public: | |||||
{ | { | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
for (int i = 0; i < m_size.y; i += MAX_LINES * 2) | for (int i = 0; i < m_size.y; i += MAX_LINES * 2) | ||||
m_donequeue.Pop(); | |||||
m_donequeue.pop(); | |||||
#endif | #endif | ||||
m_dirty[m_frame]--; | m_dirty[m_frame]--; | ||||
@@ -556,8 +556,8 @@ private: | |||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
/* Worker threads */ | /* Worker threads */ | ||||
Thread *m_threads[MAX_THREADS]; | |||||
Queue<int> m_spawnqueue, m_jobqueue, m_donequeue; | |||||
thread *m_threads[MAX_THREADS]; | |||||
queue<int> m_spawnqueue, m_jobqueue, m_donequeue; | |||||
#endif | #endif | ||||
#if !defined __native_client__ | #if !defined __native_client__ | ||||
@@ -1,11 +1,14 @@ | |||||
// | // | ||||
// Lol Engine | |||||
// Lol Engine | |||||
// | // | ||||
// Copyright: (c) 2010-2011 Sam Hocevar <sam@hocevar.net> | |||||
// This program is free software; you can redistribute it and/or | |||||
// modify it under the terms of the Do What The Fuck You Want To | |||||
// Public License, Version 2, as published by Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net> | |||||
// © 2013—2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
// | |||||
// This library is free software. It comes without any warranty, to | |||||
// the extent permitted by applicable law. You can redistribute it | |||||
// and/or modify it under the terms of the Do What the Fuck You Want | |||||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||||
// See http://www.wtfpl.net/ for more details. | |||||
// | // | ||||
#pragma once | #pragma once | ||||
@@ -23,27 +26,29 @@ | |||||
#include "entity.h" | #include "entity.h" | ||||
#include <functional> | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
class Mutex : public MutexBase | |||||
class mutex : public mutex_base | |||||
{ | { | ||||
public: | public: | ||||
Mutex() : MutexBase() {} | |||||
mutex() : mutex_base() {} | |||||
}; | }; | ||||
template<typename T, int N = 128> class Queue : public QueueBase<T, N> | |||||
template<typename T, int N = 128> class queue : public queue_base<T, N> | |||||
{ | { | ||||
public: | public: | ||||
Queue() : QueueBase<T, N>() {} | |||||
queue() : queue_base<T, N>() {} | |||||
}; | }; | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
class Thread : ThreadBase | |||||
class thread : thread_base | |||||
{ | { | ||||
public: | public: | ||||
Thread(void *(*fn)(void *), void *data) : ThreadBase(fn, data) {} | |||||
virtual ~Thread() {} | |||||
thread(std::function<void(void)> fn) : thread_base(fn) {} | |||||
virtual ~thread() {} | |||||
}; | }; | ||||
struct ThreadStatus | struct ThreadStatus | ||||
@@ -104,18 +109,19 @@ protected: | |||||
//Fetch Results | //Fetch Results | ||||
bool FetchResult(array<ThreadJob*>& results); | bool FetchResult(array<ThreadJob*>& results); | ||||
//Base thread work function | //Base thread work function | ||||
static void *BaseThreadWork(void* data); | |||||
void BaseThreadWork(); | |||||
virtual void TickGame(float seconds); | virtual void TickGame(float seconds); | ||||
//Default behaviour : delete the job result | //Default behaviour : delete the job result | ||||
virtual void TreatResult(ThreadJob* result) { delete(result); } | virtual void TreatResult(ThreadJob* result) { delete(result); } | ||||
/* Worker threads */ | /* Worker threads */ | ||||
int m_thread_count; | |||||
array<Thread*> m_threads; | |||||
Queue<ThreadStatus> m_spawnqueue, m_donequeue; | |||||
Queue<ThreadJob*> m_jobqueue; | |||||
Queue<ThreadJob*> m_resultqueue; | |||||
array<ThreadJob*> m_job_dispatch; | |||||
int m_thread_count; | |||||
array<thread*> m_threads; | |||||
queue<ThreadStatus> m_spawnqueue, m_donequeue; | |||||
queue<ThreadJob*> m_jobqueue; | |||||
queue<ThreadJob*> m_resultqueue; | |||||
array<ThreadJob*> m_job_dispatch; | |||||
}; | }; | ||||
//Generic class for thread manager, executes work and store results, for you to use | //Generic class for thread manager, executes work and store results, for you to use | ||||
@@ -69,8 +69,8 @@ void NaClInstance::TickCallback(void* data, int32_t result) | |||||
instance->m_input_data->Tick(DELTA_MS); | instance->m_input_data->Tick(DELTA_MS); | ||||
} | } | ||||
Mutex NaClInstance::main_mutex; | |||||
Queue<NaClInstance::Args *, 1> NaClInstance::main_queue; | |||||
mutex NaClInstance::main_mutex; | |||||
queue<NaClInstance::Args *, 1> NaClInstance::main_queue; | |||||
bool NaClInstance::Init(uint32_t argc, | bool NaClInstance::Init(uint32_t argc, | ||||
const char* /* argn */[], | const char* /* argn */[], | ||||
@@ -81,7 +81,7 @@ bool NaClInstance::Init(uint32_t argc, | |||||
char *env[] = { nullptr }; | char *env[] = { nullptr }; | ||||
Args arglist(argc, const_cast<char **>(argv), const_cast<char **>(env)); | Args arglist(argc, const_cast<char **>(argv), const_cast<char **>(env)); | ||||
main_queue.Push(&arglist); | main_queue.Push(&arglist); | ||||
m_main_thread = new Thread(MainRun, nullptr); | |||||
m_main_thread = new thread(MainRun, nullptr); | |||||
/* Push so that only MainSignal() can unblock us */ | /* Push so that only MainSignal() can unblock us */ | ||||
main_queue.Push(nullptr); | main_queue.Push(nullptr); | ||||
main_queue.Push(nullptr); | main_queue.Push(nullptr); | ||||
@@ -96,8 +96,8 @@ private: | |||||
char **m_argv; | char **m_argv; | ||||
char **m_env; | char **m_env; | ||||
}; | }; | ||||
static Mutex main_mutex; | |||||
static Queue<Args *, 1> main_queue; | |||||
static mutex main_mutex; | |||||
static queue<Args *, 1> main_queue; | |||||
Thread *m_main_thread; | Thread *m_main_thread; | ||||
}; | }; | ||||
@@ -1,12 +1,14 @@ | |||||
// | // | ||||
// Lol Engine | |||||
// Lol Engine | |||||
// | // | ||||
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
// 2014 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
// This program is free software; you can redistribute it and/or | |||||
// modify it under the terms of the Do What The Fuck You Want To | |||||
// Public License, Version 2, as published by Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net> | |||||
// © 2014—2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
// | |||||
// This library is free software. It comes without any warranty, to | |||||
// the extent permitted by applicable law. You can redistribute it | |||||
// and/or modify it under the terms of the Do What the Fuck You Want | |||||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||||
// See http://www.wtfpl.net/ for more details. | |||||
// | // | ||||
#include <lol/engine-internal.h> | #include <lol/engine-internal.h> | ||||
@@ -34,9 +36,10 @@ bool BaseThreadManager::Start() | |||||
/* Spawn worker threads and wait for their readiness. */ | /* Spawn worker threads and wait for their readiness. */ | ||||
m_threads.Resize(m_thread_count); | m_threads.Resize(m_thread_count); | ||||
for (int i = 0; i < m_thread_count; i++) | for (int i = 0; i < m_thread_count; i++) | ||||
m_threads[i] = new Thread(BaseThreadWork, this); | |||||
m_threads[i] = new thread(std::bind(&BaseThreadManager::BaseThreadWork, | |||||
this)); | |||||
for (int i = 0; i < m_thread_count; i++) | for (int i = 0; i < m_thread_count; i++) | ||||
m_spawnqueue.Pop(); | |||||
m_spawnqueue.pop(); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -51,9 +54,9 @@ bool BaseThreadManager::Stop() | |||||
* them to quit. */ | * them to quit. */ | ||||
ThreadJob stop_job(ThreadJobType::THREAD_STOP); | ThreadJob stop_job(ThreadJobType::THREAD_STOP); | ||||
for (int i = 0; i < m_thread_count; i++) | for (int i = 0; i < m_thread_count; i++) | ||||
m_jobqueue.Push(&stop_job); | |||||
m_jobqueue.push(&stop_job); | |||||
for (int i = 0; i < m_thread_count; i++) | for (int i = 0; i < m_thread_count; i++) | ||||
m_donequeue.Pop(); | |||||
m_donequeue.pop(); | |||||
return true; | return true; | ||||
} | } | ||||
@@ -61,7 +64,7 @@ bool BaseThreadManager::Stop() | |||||
//Work stuff | //Work stuff | ||||
bool BaseThreadManager::AddWork(ThreadJob* job) | bool BaseThreadManager::AddWork(ThreadJob* job) | ||||
{ | { | ||||
if (m_jobqueue.TryPush(job)) | |||||
if (m_jobqueue.try_push(job)) | |||||
return true; | return true; | ||||
return false; | return false; | ||||
} | } | ||||
@@ -69,19 +72,18 @@ bool BaseThreadManager::AddWork(ThreadJob* job) | |||||
bool BaseThreadManager::FetchResult(array<ThreadJob*>& results) | bool BaseThreadManager::FetchResult(array<ThreadJob*>& results) | ||||
{ | { | ||||
ThreadJob* result; | ThreadJob* result; | ||||
while (m_resultqueue.TryPop(result)) | |||||
while (m_resultqueue.try_pop(result)) | |||||
results << result; | results << result; | ||||
return results.Count() > 0; | return results.Count() > 0; | ||||
} | } | ||||
//Base thread work function | //Base thread work function | ||||
void *BaseThreadManager::BaseThreadWork(void* data) | |||||
void BaseThreadManager::BaseThreadWork() | |||||
{ | { | ||||
BaseThreadManager *that = (BaseThreadManager *)data; | |||||
that->m_spawnqueue.Push(ThreadStatus::THREAD_STARTED); | |||||
m_spawnqueue.push(ThreadStatus::THREAD_STARTED); | |||||
for ( ; ; ) | for ( ; ; ) | ||||
{ | { | ||||
ThreadJob* job = that->m_jobqueue.Pop(); | |||||
ThreadJob* job = m_jobqueue.pop(); | |||||
if (job->GetJobType() == ThreadJobType::THREAD_STOP) | if (job->GetJobType() == ThreadJobType::THREAD_STOP) | ||||
break; | break; | ||||
else if (*job == ThreadJobType::WORK_TODO) | else if (*job == ThreadJobType::WORK_TODO) | ||||
@@ -90,11 +92,10 @@ void *BaseThreadManager::BaseThreadWork(void* data) | |||||
job->SetJobType(ThreadJobType::WORK_DONE); | job->SetJobType(ThreadJobType::WORK_DONE); | ||||
else | else | ||||
job->SetJobType(ThreadJobType::WORK_FAILED); | job->SetJobType(ThreadJobType::WORK_FAILED); | ||||
that->m_resultqueue.Push(job); | |||||
m_resultqueue.push(job); | |||||
} | } | ||||
} | } | ||||
that->m_donequeue.Push(ThreadStatus::THREAD_STOPPED); | |||||
return nullptr; | |||||
m_donequeue.push(ThreadStatus::THREAD_STOPPED); | |||||
} | } | ||||
void BaseThreadManager::TickGame(float seconds) | void BaseThreadManager::TickGame(float seconds) | ||||
@@ -106,7 +107,7 @@ void BaseThreadManager::TickGame(float seconds) | |||||
//Dispatch work task | //Dispatch work task | ||||
while (m_job_dispatch.Count() > 0 && AddWork(m_job_dispatch.Last())) | while (m_job_dispatch.Count() > 0 && AddWork(m_job_dispatch.Last())) | ||||
m_job_dispatch.Pop(); | |||||
m_job_dispatch.pop(); | |||||
array<ThreadJob*> result; | array<ThreadJob*> result; | ||||
//Fetch and treat results | //Fetch and treat results | ||||
@@ -1,18 +1,21 @@ | |||||
// | // | ||||
// Lol Engine | |||||
// Lol Engine | |||||
// | // | ||||
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||||
// This program is free software; you can redistribute it and/or | |||||
// modify it under the terms of the Do What The Fuck You Want To | |||||
// Public License, Version 2, as published by Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net> | |||||
// © 2014—2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
// | |||||
// This library is free software. It comes without any warranty, to | |||||
// the extent permitted by applicable law. You can redistribute it | |||||
// and/or modify it under the terms of the Do What the Fuck You Want | |||||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||||
// See http://www.wtfpl.net/ for more details. | |||||
// | // | ||||
#pragma once | #pragma once | ||||
// | // | ||||
// The ThreadBase class | |||||
// -------------------- | |||||
// The base classes for multithreading | |||||
// ----------------------------------- | |||||
// | // | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
@@ -32,10 +35,10 @@ | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
class MutexBase | |||||
class mutex_base | |||||
{ | { | ||||
public: | public: | ||||
MutexBase() | |||||
mutex_base() | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_mutex_init(&m_mutex, nullptr); | pthread_mutex_init(&m_mutex, nullptr); | ||||
@@ -44,7 +47,7 @@ public: | |||||
#endif | #endif | ||||
} | } | ||||
~MutexBase() | |||||
~mutex_base() | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_mutex_destroy(&m_mutex); | pthread_mutex_destroy(&m_mutex); | ||||
@@ -53,7 +56,7 @@ public: | |||||
#endif | #endif | ||||
} | } | ||||
void Lock() | |||||
void lock() | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_mutex_lock(&m_mutex); | pthread_mutex_lock(&m_mutex); | ||||
@@ -62,7 +65,7 @@ public: | |||||
#endif | #endif | ||||
} | } | ||||
void Unlock() | |||||
void unlock() | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_mutex_unlock(&m_mutex); | pthread_mutex_unlock(&m_mutex); | ||||
@@ -79,10 +82,11 @@ private: | |||||
#endif | #endif | ||||
}; | }; | ||||
template<typename T, int N> class QueueBase | |||||
template<typename T, int N> | |||||
class queue_base | |||||
{ | { | ||||
public: | public: | ||||
QueueBase() | |||||
queue_base() | |||||
{ | { | ||||
m_start = m_count = 0; | m_start = m_count = 0; | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
@@ -97,7 +101,7 @@ public: | |||||
#endif | #endif | ||||
} | } | ||||
~QueueBase() | |||||
~queue_base() | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_cond_destroy(&m_empty_cond); | pthread_cond_destroy(&m_empty_cond); | ||||
@@ -110,7 +114,7 @@ public: | |||||
#endif | #endif | ||||
} | } | ||||
void Push(T value) | |||||
void push(T value) | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_mutex_lock(&m_mutex); | pthread_mutex_lock(&m_mutex); | ||||
@@ -139,7 +143,7 @@ public: | |||||
#endif | #endif | ||||
} | } | ||||
bool TryPush(T value) | |||||
bool try_push(T value) | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_mutex_lock(&m_mutex); | pthread_mutex_lock(&m_mutex); | ||||
@@ -173,7 +177,7 @@ public: | |||||
return true; | return true; | ||||
} | } | ||||
T Pop() | |||||
T pop() | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_mutex_lock(&m_mutex); | pthread_mutex_lock(&m_mutex); | ||||
@@ -207,7 +211,7 @@ public: | |||||
return ret; | return ret; | ||||
} | } | ||||
bool TryPop(T &ret) | |||||
bool try_pop(T &ret) | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_mutex_lock(&m_mutex); | pthread_mutex_lock(&m_mutex); | ||||
@@ -255,24 +259,24 @@ private: | |||||
#endif | #endif | ||||
}; | }; | ||||
class ThreadBase | |||||
class thread_base | |||||
{ | { | ||||
public: | public: | ||||
ThreadBase(void *(*fn)(void *), void *data) | |||||
thread_base(std::function<void(void)>) | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
/* Set the joinable attribute for systems who don't play nice */ | /* Set the joinable attribute for systems who don't play nice */ | ||||
pthread_attr_t attr; | pthread_attr_t attr; | ||||
pthread_attr_init(&attr); | pthread_attr_init(&attr); | ||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); | ||||
pthread_create(&m_thread, &attr, fn, data); | |||||
pthread_create(&m_thread, &attr, trampoline, this); | |||||
#elif defined _WIN32 | #elif defined _WIN32 | ||||
m_thread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)fn, | |||||
data, 0, &m_tid); | |||||
m_thread = CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)trampoline, | |||||
this, 0, &m_tid); | |||||
#endif | #endif | ||||
} | } | ||||
virtual ~ThreadBase() | |||||
virtual ~thread_base() | |||||
{ | { | ||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_join(m_thread, nullptr); | pthread_join(m_thread, nullptr); | ||||
@@ -282,6 +286,15 @@ public: | |||||
} | } | ||||
private: | private: | ||||
static void *trampoline(void *data) | |||||
{ | |||||
thread_base *that = (thread_base *)data; | |||||
that->m_function(); | |||||
return nullptr; | |||||
} | |||||
std::function<void(void)> m_function; | |||||
#if defined HAVE_PTHREAD_H | #if defined HAVE_PTHREAD_H | ||||
pthread_t m_thread; | pthread_t m_thread; | ||||
#elif defined _WIN32 | #elif defined _WIN32 | ||||
@@ -1,11 +1,14 @@ | |||||
// | // | ||||
// Lol Engine | |||||
// Lol Engine | |||||
// | // | ||||
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net> | |||||
// This program is free software; you can redistribute it and/or | |||||
// modify it under the terms of the Do What The Fuck You Want To | |||||
// Public License, Version 2, as published by Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net> | |||||
// © 2014—2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||||
// | |||||
// This program is free software. It comes without any warranty, to | |||||
// the extent permitted by applicable law. You can redistribute it | |||||
// and/or modify it under the terms of the Do What the Fuck You Want | |||||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||||
// See http://www.wtfpl.net/ for more details. | |||||
// | // | ||||
#include <lol/engine-internal.h> | #include <lol/engine-internal.h> | ||||
@@ -15,35 +18,35 @@ | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
lolunit_declare_fixture(ThreadTest) | |||||
lolunit_declare_fixture(thread_test) | |||||
{ | { | ||||
void SetUp() {} | void SetUp() {} | ||||
void TearDown() {} | void TearDown() {} | ||||
lolunit_declare_test(QueueTryPush) | |||||
lolunit_declare_test(queue_try_push) | |||||
{ | { | ||||
Queue<int, 1> q; | |||||
queue<int, 1> q; | |||||
bool b1 = q.TryPush(0); | |||||
bool b1 = q.try_push(0); | |||||
lolunit_assert_equal(true, b1); | lolunit_assert_equal(true, b1); | ||||
bool b2 = q.TryPush(1); | |||||
bool b2 = q.try_push(1); | |||||
lolunit_assert_equal(false, b2); | lolunit_assert_equal(false, b2); | ||||
} | } | ||||
lolunit_declare_test(QueueTryPop) | |||||
lolunit_declare_test(queue_try_pop) | |||||
{ | { | ||||
Queue<int, 1> q; | |||||
queue<int, 1> q; | |||||
int tmp; | int tmp; | ||||
q.Push(42); | |||||
q.push(42); | |||||
bool b1 = q.TryPop(tmp); | |||||
bool b1 = q.try_pop(tmp); | |||||
lolunit_assert_equal(true, b1); | lolunit_assert_equal(true, b1); | ||||
lolunit_assert_equal(42, tmp); | lolunit_assert_equal(42, tmp); | ||||
bool b2 = q.TryPop(tmp); | |||||
bool b2 = q.try_pop(tmp); | |||||
lolunit_assert_equal(false, b2); | lolunit_assert_equal(false, b2); | ||||
lolunit_assert_equal(42, tmp); | lolunit_assert_equal(42, tmp); | ||||
} | } | ||||
@@ -1,17 +1,20 @@ | |||||
// | // | ||||
// Lol Engine | |||||
// Lol Engine | |||||
// | // | ||||
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||||
// This program is free software; you can redistribute it and/or | |||||
// modify it under the terms of the Do What The Fuck You Want To | |||||
// Public License, Version 2, as published by Sam Hocevar. See | |||||
// http://www.wtfpl.net/ for more details. | |||||
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net> | |||||
// | |||||
// This library is free software. It comes without any warranty, to | |||||
// the extent permitted by applicable law. You can redistribute it | |||||
// and/or modify it under the terms of the Do What the Fuck You Want | |||||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||||
// See http://www.wtfpl.net/ for more details. | |||||
// | // | ||||
#include <lol/engine-internal.h> | #include <lol/engine-internal.h> | ||||
#include <cstdlib> | #include <cstdlib> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <functional> | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -44,8 +47,8 @@ public: | |||||
Log::Debug("%d frames required to quit\n", frame - quitframe); | Log::Debug("%d frames required to quit\n", frame - quitframe); | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
gametick.Push(0); | |||||
disktick.Push(0); | |||||
gametick.push(0); | |||||
disktick.push(0); | |||||
delete gamethread; | delete gamethread; | ||||
delete diskthread; | delete diskthread; | ||||
#endif | #endif | ||||
@@ -72,11 +75,11 @@ private: | |||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
/* The associated background threads */ | /* The associated background threads */ | ||||
static void *GameThreadMain(void *p); | |||||
static void *DrawThreadMain(void *p); /* unused */ | |||||
static void *DiskThreadMain(void *p); | |||||
Thread *gamethread, *drawthread, *diskthread; | |||||
Queue<int> gametick, drawtick, disktick; | |||||
void GameThreadMain(); | |||||
void DrawThreadMain(); /* unused */ | |||||
void DiskThreadMain(); | |||||
thread *gamethread, *drawthread, *diskthread; | |||||
queue<int> gametick, drawtick, disktick; | |||||
#endif | #endif | ||||
/* Shutdown management */ | /* Shutdown management */ | ||||
@@ -95,10 +98,10 @@ void Ticker::Register(Entity *entity) | |||||
/* If we are called from its constructor, the object's vtable is not | /* If we are called from its constructor, the object's vtable is not | ||||
* ready yet, so we do not know which group this entity belongs to. Wait | * ready yet, so we do not know which group this entity belongs to. Wait | ||||
* until the first tick. */ | * until the first tick. */ | ||||
data->m_todolist.Push(entity); | |||||
data->m_todolist.push(entity); | |||||
/* Objects are autoreleased by default. Put them in a list. */ | /* Objects are autoreleased by default. Put them in a list. */ | ||||
data->m_autolist.Push(entity); | |||||
data->m_autolist.push(entity); | |||||
entity->m_autorelease = 1; | entity->m_autorelease = 1; | ||||
entity->m_ref = 1; | entity->m_ref = 1; | ||||
@@ -143,7 +146,7 @@ int Ticker::Unref(Entity *entity) | |||||
} | } | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
void *TickerData::GameThreadMain(void * /* p */) | |||||
void TickerData::GameThreadMain() | |||||
{ | { | ||||
#if LOL_BUILD_DEBUG | #if LOL_BUILD_DEBUG | ||||
Log::Info("ticker game thread initialised\n"); | Log::Info("ticker game thread initialised\n"); | ||||
@@ -151,27 +154,25 @@ void *TickerData::GameThreadMain(void * /* p */) | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
int tick = data->gametick.Pop(); | |||||
int tick = gametick.pop(); | |||||
if (!tick) | if (!tick) | ||||
break; | break; | ||||
GameThreadTick(); | GameThreadTick(); | ||||
data->drawtick.Push(1); | |||||
drawtick.push(1); | |||||
} | } | ||||
data->drawtick.Push(0); | |||||
drawtick.push(0); | |||||
#if LOL_BUILD_DEBUG | #if LOL_BUILD_DEBUG | ||||
Log::Info("ticker game thread terminated\n"); | Log::Info("ticker game thread terminated\n"); | ||||
#endif | #endif | ||||
return nullptr; | |||||
} | } | ||||
#endif /* LOL_FEATURE_THREADS */ | #endif /* LOL_FEATURE_THREADS */ | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
void *TickerData::DrawThreadMain(void * /* p */) | |||||
void TickerData::DrawThreadMain() | |||||
{ | { | ||||
#if LOL_BUILD_DEBUG | #if LOL_BUILD_DEBUG | ||||
Log::Info("ticker draw thread initialised\n"); | Log::Info("ticker draw thread initialised\n"); | ||||
@@ -179,30 +180,26 @@ void *TickerData::DrawThreadMain(void * /* p */) | |||||
for (;;) | for (;;) | ||||
{ | { | ||||
int tick = data->drawtick.Pop(); | |||||
int tick = drawtick.pop(); | |||||
if (!tick) | if (!tick) | ||||
break; | break; | ||||
DrawThreadTick(); | DrawThreadTick(); | ||||
data->gametick.Push(1); | |||||
gametick.push(1); | |||||
} | } | ||||
#if LOL_BUILD_DEBUG | #if LOL_BUILD_DEBUG | ||||
Log::Info("ticker draw thread terminated\n"); | Log::Info("ticker draw thread terminated\n"); | ||||
#endif | #endif | ||||
return nullptr; | |||||
} | } | ||||
#endif /* LOL_FEATURE_THREADS */ | #endif /* LOL_FEATURE_THREADS */ | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
void *TickerData::DiskThreadMain(void * /* p */) | |||||
void TickerData::DiskThreadMain() | |||||
{ | { | ||||
/* FIXME: temporary hack to avoid crashes on the PS3 */ | /* FIXME: temporary hack to avoid crashes on the PS3 */ | ||||
data->disktick.Pop(); | |||||
return nullptr; | |||||
disktick.pop(); | |||||
} | } | ||||
#endif /* LOL_FEATURE_THREADS */ | #endif /* LOL_FEATURE_THREADS */ | ||||
@@ -437,17 +434,17 @@ void Ticker::Setup(float fps) | |||||
data->fps = fps; | data->fps = fps; | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
data->gamethread = new Thread(TickerData::GameThreadMain, nullptr); | |||||
data->gametick.Push(1); | |||||
data->gamethread = new thread(std::bind(&TickerData::GameThreadMain, data)); | |||||
data->gametick.push(1); | |||||
data->diskthread = new Thread(TickerData::DiskThreadMain, nullptr); | |||||
data->diskthread = new thread(std::bind(&TickerData::DiskThreadMain, data)); | |||||
#endif | #endif | ||||
} | } | ||||
void Ticker::TickDraw() | void Ticker::TickDraw() | ||||
{ | { | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
data->drawtick.Pop(); | |||||
data->drawtick.pop(); | |||||
#else | #else | ||||
TickerData::GameThreadTick(); | TickerData::GameThreadTick(); | ||||
#endif | #endif | ||||
@@ -458,7 +455,7 @@ void Ticker::TickDraw() | |||||
/* Signal game thread that it can carry on */ | /* Signal game thread that it can carry on */ | ||||
#if LOL_FEATURE_THREADS | #if LOL_FEATURE_THREADS | ||||
data->gametick.Push(1); | |||||
data->gametick.push(1); | |||||
#else | #else | ||||
TickerData::DiskThreadTick(); | TickerData::DiskThreadTick(); | ||||
#endif | #endif | ||||