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