diff --git a/src/lol/sys/thread.h b/src/lol/sys/thread.h index 30d081f8..b93d1051 100644 --- a/src/lol/sys/thread.h +++ b/src/lol/sys/thread.h @@ -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& 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& results); + //Base thread work function + static void *BaseThreadWork(void* data); + virtual void TickGame(float seconds); + virtual void TreatResult(ThreadJob* result) { } + + char const *GetName() { return ""; } protected: /* Worker threads */ @@ -180,6 +126,7 @@ protected: Queue m_spawnqueue, m_donequeue; Queue m_jobqueue; Queue m_resultqueue; + Array m_job_dispatch; }; #endif diff --git a/src/lolcore.vcxproj b/src/lolcore.vcxproj index dedf571f..8f7ae5a6 100644 --- a/src/lolcore.vcxproj +++ b/src/lolcore.vcxproj @@ -226,6 +226,7 @@ + diff --git a/src/sys/file.cpp b/src/sys/file.cpp index 739f5a1b..acdc387a 100644 --- a/src/sys/file.cpp +++ b/src/sys/file.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 diff --git a/src/sys/thread.cpp b/src/sys/thread.cpp new file mode 100644 index 00000000..3621b3cc --- /dev/null +++ b/src/sys/thread.cpp @@ -0,0 +1,126 @@ +// +// Lol Engine +// +// Copyright: (c) 2010-2014 Sam Hocevar +// 2014 Benjamin "Touky" Huet +// 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& 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 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 */ diff --git a/src/tileset.cpp b/src/tileset.cpp index d9d7227d..a044323f 100644 --- a/src/tileset.cpp +++ b/src/tileset.cpp @@ -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;