| @@ -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 | ||||