| @@ -22,6 +22,8 @@ | |||||
| # include "sys/threadbase.h" | # include "sys/threadbase.h" | ||||
| #endif | #endif | ||||
| #include "entity.h" | |||||
| namespace lol | namespace lol | ||||
| { | { | ||||
| @@ -69,6 +71,7 @@ struct ThreadJobType | |||||
| NONE = 0, | NONE = 0, | ||||
| WORK_TODO, | WORK_TODO, | ||||
| WORK_DONE, | WORK_DONE, | ||||
| WORK_FAILED, | |||||
| THREAD_STOP, | THREAD_STOP, | ||||
| MAX | MAX | ||||
| @@ -96,82 +99,25 @@ protected: | |||||
| ThreadJobType m_type; | ThreadJobType m_type; | ||||
| }; | }; | ||||
| class ThreadManager | |||||
| class ThreadManager : public Entity | |||||
| { | { | ||||
| public: | public: | ||||
| ThreadManager(int thread_count) | |||||
| { | |||||
| m_thread_count = thread_count; | |||||
| } | |||||
| //Initialize and start the thread | |||||
| bool Start() | |||||
| { | |||||
| if (m_threads.Count() > 0) | |||||
| return false; | |||||
| /* Spawn worker threads and wait for their readiness. */ | |||||
| m_threads.Resize(m_thread_count); | |||||
| for (int i = 0; i < m_thread_count; i++) | |||||
| m_threads[i] = new Thread(BaseThreadWork, this); | |||||
| for (int i = 0; i < m_thread_count; i++) | |||||
| m_spawnqueue.Pop(); | |||||
| return true; | |||||
| } | |||||
| bool AddWork(ThreadJob* job) | |||||
| { | |||||
| if (m_jobqueue.TryPush(job)) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| bool FetchResult(Array<ThreadJob*>& results) | |||||
| { | |||||
| ThreadJob* result; | |||||
| while (m_resultqueue.TryPop(result)) | |||||
| results << result; | |||||
| return results.Count() > 0; | |||||
| } | |||||
| static void *BaseThreadWork(void* data) | |||||
| { | |||||
| ThreadManager *that = (ThreadManager *)data; | |||||
| that->m_spawnqueue.Push(ThreadStatus::THREAD_STARTED); | |||||
| for ( ; ; ) | |||||
| { | |||||
| ThreadJob* job = that->m_jobqueue.Pop(); | |||||
| if (job->GetJobType() == ThreadJobType::THREAD_STOP) | |||||
| break; | |||||
| else if (*job == ThreadJobType::WORK_TODO) | |||||
| { | |||||
| if (job->DoWork()) | |||||
| { | |||||
| job->SetJobType(ThreadJobType::WORK_DONE); | |||||
| that->m_resultqueue.Push(job); | |||||
| } | |||||
| } | |||||
| } | |||||
| that->m_donequeue.Push(ThreadStatus::THREAD_STOPPED); | |||||
| return NULL; | |||||
| } | |||||
| //Stop the thread | |||||
| bool Stop() | |||||
| { | |||||
| if (m_threads.Count() <= 0) | |||||
| return false; | |||||
| /* Signal worker threads for completion and wait for | |||||
| * them to quit. */ | |||||
| ThreadJob stop_job(ThreadJobType::THREAD_STOP); | |||||
| for (int i = 0; i < m_thread_count; i++) | |||||
| m_jobqueue.Push(&stop_job); | |||||
| for (int i = 0; i < m_thread_count; i++) | |||||
| m_donequeue.Pop(); | |||||
| return true; | |||||
| } | |||||
| ThreadManager(int thread_count); | |||||
| ~ThreadManager(); | |||||
| //Initialize, Ticker::Ref and start the thread | |||||
| bool Start(); | |||||
| //Stop the threads | |||||
| bool Stop(); | |||||
| //Work stuff | |||||
| bool AddWork(ThreadJob* job); | |||||
| bool FetchResult(Array<ThreadJob*>& results); | |||||
| //Base thread work function | |||||
| static void *BaseThreadWork(void* data); | |||||
| virtual void TickGame(float seconds); | |||||
| virtual void TreatResult(ThreadJob* result) { } | |||||
| char const *GetName() { return "<ThreadManager>"; } | |||||
| protected: | protected: | ||||
| /* Worker threads */ | /* Worker threads */ | ||||
| @@ -180,6 +126,7 @@ protected: | |||||
| Queue<ThreadStatus> m_spawnqueue, m_donequeue; | Queue<ThreadStatus> m_spawnqueue, m_donequeue; | ||||
| Queue<ThreadJob*> m_jobqueue; | Queue<ThreadJob*> m_jobqueue; | ||||
| Queue<ThreadJob*> m_resultqueue; | Queue<ThreadJob*> m_resultqueue; | ||||
| Array<ThreadJob*> m_job_dispatch; | |||||
| }; | }; | ||||
| #endif | #endif | ||||
| @@ -226,6 +226,7 @@ | |||||
| <ClCompile Include="sprite.cpp" /> | <ClCompile Include="sprite.cpp" /> | ||||
| <ClCompile Include="sys\file.cpp" /> | <ClCompile Include="sys\file.cpp" /> | ||||
| <ClCompile Include="sys\init.cpp" /> | <ClCompile Include="sys\init.cpp" /> | ||||
| <ClCompile Include="sys\thread.cpp" /> | |||||
| <ClCompile Include="sys\timer.cpp" /> | <ClCompile Include="sys\timer.cpp" /> | ||||
| <ClCompile Include="text.cpp" /> | <ClCompile Include="text.cpp" /> | ||||
| <ClCompile Include="ticker.cpp" /> | <ClCompile Include="ticker.cpp" /> | ||||
| @@ -444,7 +444,7 @@ class DirectoryData | |||||
| } | } | ||||
| } | } | ||||
| //Go for next one | //Go for next one | ||||
| file_valid = FindNextFile(m_handle, &find_data); | |||||
| file_valid = (bool)FindNextFile(m_handle, &find_data); | |||||
| } | } | ||||
| #elif HAVE_STDIO_H | #elif HAVE_STDIO_H | ||||
| /* FIXME: not implemented */ | /* FIXME: not implemented */ | ||||
| @@ -609,7 +609,7 @@ bool Directory::SetCurrent(String directory) | |||||
| #elif WIN32 | #elif WIN32 | ||||
| String result = directory; | String result = directory; | ||||
| result.Replace('/', '\\', true); | result.Replace('/', '\\', true); | ||||
| return SetCurrentDirectory(result.C()); | |||||
| return (bool)SetCurrentDirectory(result.C()); | |||||
| #elif HAVE_STDIO_H | #elif HAVE_STDIO_H | ||||
| /* FIXME: not implemented */ | /* FIXME: not implemented */ | ||||
| #endif | #endif | ||||
| @@ -0,0 +1,126 @@ | |||||
| // | |||||
| // 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. | |||||
| // | |||||
| #if HAVE_CONFIG_H | |||||
| # include "config.h" | |||||
| #endif | |||||
| #include "core.h" | |||||
| namespace lol | |||||
| { | |||||
| #if LOL_FEATURE_THREADS | |||||
| ThreadManager::ThreadManager(int thread_count) | |||||
| { | |||||
| m_thread_count = thread_count; | |||||
| } | |||||
| ThreadManager::~ThreadManager() | |||||
| { | |||||
| Stop(); | |||||
| } | |||||
| //Initialize, Ticker::Ref and start the thread | |||||
| bool ThreadManager::Start() | |||||
| { | |||||
| if (m_threads.Count() > 0) | |||||
| return false; | |||||
| /* Spawn worker threads and wait for their readiness. */ | |||||
| m_threads.Resize(m_thread_count); | |||||
| for (int i = 0; i < m_thread_count; i++) | |||||
| m_threads[i] = new Thread(BaseThreadWork, this); | |||||
| for (int i = 0; i < m_thread_count; i++) | |||||
| m_spawnqueue.Pop(); | |||||
| return true; | |||||
| } | |||||
| //Stop the threads | |||||
| bool ThreadManager::Stop() | |||||
| { | |||||
| if (m_threads.Count() <= 0) | |||||
| return false; | |||||
| /* Signal worker threads for completion and wait for | |||||
| * them to quit. */ | |||||
| ThreadJob stop_job(ThreadJobType::THREAD_STOP); | |||||
| for (int i = 0; i < m_thread_count; i++) | |||||
| m_jobqueue.Push(&stop_job); | |||||
| for (int i = 0; i < m_thread_count; i++) | |||||
| m_donequeue.Pop(); | |||||
| return true; | |||||
| } | |||||
| //Work stuff | |||||
| bool ThreadManager::AddWork(ThreadJob* job) | |||||
| { | |||||
| if (m_jobqueue.TryPush(job)) | |||||
| return true; | |||||
| return false; | |||||
| } | |||||
| bool ThreadManager::FetchResult(Array<ThreadJob*>& results) | |||||
| { | |||||
| ThreadJob* result; | |||||
| while (m_resultqueue.TryPop(result)) | |||||
| results << result; | |||||
| return results.Count() > 0; | |||||
| } | |||||
| //Base thread work function | |||||
| void *ThreadManager::BaseThreadWork(void* data) | |||||
| { | |||||
| ThreadManager *that = (ThreadManager *)data; | |||||
| that->m_spawnqueue.Push(ThreadStatus::THREAD_STARTED); | |||||
| for ( ; ; ) | |||||
| { | |||||
| ThreadJob* job = that->m_jobqueue.Pop(); | |||||
| if (job->GetJobType() == ThreadJobType::THREAD_STOP) | |||||
| break; | |||||
| else if (*job == ThreadJobType::WORK_TODO) | |||||
| { | |||||
| if (job->DoWork()) | |||||
| job->SetJobType(ThreadJobType::WORK_DONE); | |||||
| else | |||||
| job->SetJobType(ThreadJobType::WORK_FAILED); | |||||
| that->m_resultqueue.Push(job); | |||||
| } | |||||
| } | |||||
| that->m_donequeue.Push(ThreadStatus::THREAD_STOPPED); | |||||
| return NULL; | |||||
| } | |||||
| void ThreadManager::TickGame(float seconds) | |||||
| { | |||||
| //Start if needed | |||||
| Start(); | |||||
| //Dispatch work task | |||||
| while (m_job_dispatch.Count() > 0 && AddWork(m_job_dispatch.Last())) | |||||
| m_job_dispatch.Pop(); | |||||
| Array<ThreadJob*> result; | |||||
| //Fetch and treat results | |||||
| if (FetchResult(result)) | |||||
| { | |||||
| for (int i = 0; i < result.Count(); i++) | |||||
| { | |||||
| ThreadJob* job = result[i]; | |||||
| if (job->GetJobType() == ThreadJobType::WORK_DONE) | |||||
| TreatResult(job); | |||||
| delete(job); | |||||
| } | |||||
| } | |||||
| } | |||||
| #endif //LOL_FEATURE_THREADS | |||||
| } /* namespace lol */ | |||||
| @@ -279,9 +279,9 @@ void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale, float angle, | |||||
| float tx = texels.A.x; | float tx = texels.A.x; | ||||
| float ty = texels.A.y; | float ty = texels.A.y; | ||||
| int dx = (pixels.B.x - pixels.A.x) * scale.x; | |||||
| int dy = o ? 0 : (pixels.B.y - pixels.A.y) * scale.y; | |||||
| int dz = o ? (pixels.B.y - pixels.A.y) * scale.y : 0; | |||||
| int dx = (pixels.B.x - pixels.A.x) * (int)scale.x; | |||||
| int dy = o ? 0 : (pixels.B.y - pixels.A.y) * (int)scale.y; | |||||
| int dz = o ? (pixels.B.y - pixels.A.y) * (int)scale.y : 0; | |||||
| /* If scaling is negative, switch triangle winding */ | /* If scaling is negative, switch triangle winding */ | ||||
| if (scale.x * scale.y < 0.0f) | if (scale.x * scale.y < 0.0f) | ||||
| @@ -301,8 +301,8 @@ void TileSet::BlitTile(uint32_t id, vec3 pos, int o, vec2 scale, float angle, | |||||
| dty *= 126.f / 128.f; | dty *= 126.f / 128.f; | ||||
| #endif | #endif | ||||
| vec3 extent_x = 0.5f * vec3(dx, 0.f, 0.f); | |||||
| vec3 extent_y = 0.5f * vec3(0.f, dy, dz); | |||||
| vec3 extent_x = 0.5f * vec3((float)dx, 0.f, 0.f); | |||||
| vec3 extent_y = 0.5f * vec3(0.f, (float)dy, (float)dz); | |||||
| vec3 center = pos + extent_x + extent_y; | vec3 center = pos + extent_x + extent_y; | ||||
| extent_x = mat3::rotate(angle, vec3::axis_z) * extent_x; | extent_x = mat3::rotate(angle, vec3::axis_z) * extent_x; | ||||
| extent_y = mat3::rotate(angle, vec3::axis_z) * extent_y; | extent_y = mat3::rotate(angle, vec3::axis_z) * extent_y; | ||||