瀏覽代碼

ThreadManager is now an entity, it's awesooooome

undefined
Benjamin ‘Touky’ Huet Sam Hocevar <sam@hocevar.net> 10 年之前
父節點
當前提交
58a0c1001a
共有 5 個文件被更改,包括 155 次插入81 次删除
  1. +21
    -74
      src/lol/sys/thread.h
  2. +1
    -0
      src/lolcore.vcxproj
  3. +2
    -2
      src/sys/file.cpp
  4. +126
    -0
      src/sys/thread.cpp
  5. +5
    -5
      src/tileset.cpp

+ 21
- 74
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<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



+ 1
- 0
src/lolcore.vcxproj 查看文件

@@ -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" />


+ 2
- 2
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


+ 126
- 0
src/sys/thread.cpp 查看文件

@@ -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 */

+ 5
- 5
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;


Loading…
取消
儲存