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