| @@ -22,6 +22,8 @@ | |||
| # include "sys/threadbase.h" | |||
| #endif | |||
| #include "entity.h" | |||
| namespace lol | |||
| { | |||
| @@ -69,6 +71,7 @@ struct ThreadJobType | |||
| NONE = 0, | |||
| WORK_TODO, | |||
| WORK_DONE, | |||
| WORK_FAILED, | |||
| THREAD_STOP, | |||
| MAX | |||
| @@ -96,82 +99,25 @@ protected: | |||
| ThreadJobType m_type; | |||
| }; | |||
| class ThreadManager | |||
| class ThreadManager : public Entity | |||
| { | |||
| 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: | |||
| /* Worker threads */ | |||
| @@ -180,6 +126,7 @@ protected: | |||
| Queue<ThreadStatus> m_spawnqueue, m_donequeue; | |||
| Queue<ThreadJob*> m_jobqueue; | |||
| Queue<ThreadJob*> m_resultqueue; | |||
| Array<ThreadJob*> m_job_dispatch; | |||
| }; | |||
| #endif | |||
| @@ -226,6 +226,7 @@ | |||
| <ClCompile Include="sprite.cpp" /> | |||
| <ClCompile Include="sys\file.cpp" /> | |||
| <ClCompile Include="sys\init.cpp" /> | |||
| <ClCompile Include="sys\thread.cpp" /> | |||
| <ClCompile Include="sys\timer.cpp" /> | |||
| <ClCompile Include="text.cpp" /> | |||
| <ClCompile Include="ticker.cpp" /> | |||
| @@ -444,7 +444,7 @@ class DirectoryData | |||
| } | |||
| } | |||
| //Go for next one | |||
| file_valid = FindNextFile(m_handle, &find_data); | |||
| file_valid = (bool)FindNextFile(m_handle, &find_data); | |||
| } | |||
| #elif HAVE_STDIO_H | |||
| /* FIXME: not implemented */ | |||
| @@ -609,7 +609,7 @@ bool Directory::SetCurrent(String directory) | |||
| #elif WIN32 | |||
| String result = directory; | |||
| result.Replace('/', '\\', true); | |||
| return SetCurrentDirectory(result.C()); | |||
| return (bool)SetCurrentDirectory(result.C()); | |||
| #elif HAVE_STDIO_H | |||
| /* FIXME: not implemented */ | |||
| #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 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 (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; | |||
| #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; | |||
| extent_x = mat3::rotate(angle, vec3::axis_z) * extent_x; | |||
| extent_y = mat3::rotate(angle, vec3::axis_z) * extent_y; | |||