Procházet zdrojové kódy

ThreadManager is now an entity, it's awesooooome

undefined
Benjamin ‘Touky’ Huet Sam Hocevar <sam@hocevar.net> před 11 roky
rodič
revize
58a0c1001a
5 změnil soubory, kde provedl 155 přidání a 81 odebrání
  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 Zobrazit soubor

@@ -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) ThreadManager(int thread_count);
{ ~ThreadManager();
m_thread_count = thread_count; //Initialize, Ticker::Ref and start the thread
} bool Start();

//Stop the threads
//Initialize and start the thread bool Stop();
bool Start() //Work stuff
{ bool AddWork(ThreadJob* job);
if (m_threads.Count() > 0) bool FetchResult(Array<ThreadJob*>& results);
return false; //Base thread work function

static void *BaseThreadWork(void* data);
/* Spawn worker threads and wait for their readiness. */ virtual void TickGame(float seconds);
m_threads.Resize(m_thread_count); virtual void TreatResult(ThreadJob* result) { }
for (int i = 0; i < m_thread_count; i++) char const *GetName() { return "<ThreadManager>"; }
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;
}


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




+ 1
- 0
src/lolcore.vcxproj Zobrazit soubor

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


+ 2
- 2
src/sys/file.cpp Zobrazit soubor

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


+ 126
- 0
src/sys/thread.cpp Zobrazit soubor

@@ -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 Zobrazit soubor

@@ -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 dx = (pixels.B.x - pixels.A.x) * (int)scale.x;
int dy = o ? 0 : (pixels.B.y - pixels.A.y) * scale.y; int dy = o ? 0 : (pixels.B.y - pixels.A.y) * (int)scale.y;
int dz = o ? (pixels.B.y - pixels.A.y) * scale.y : 0; 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_x = 0.5f * vec3((float)dx, 0.f, 0.f);
vec3 extent_y = 0.5f * vec3(0.f, dy, dz); 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;


||||||
x
 
000:0
Načítá se…
Zrušit
Uložit