Browse Source

Added Thread classes

Added InputProfile in Controller
Added ExecLuaCode
undefined
Benjamin ‘Touky’ Huet Sam Hocevar <sam@hocevar.net> 9 years ago
parent
commit
9c07e8c2e0
21 changed files with 690 additions and 63 deletions
  1. +2
    -5
      doc/samples/Makefile.am
  2. +2
    -1
      doc/samples/meshviewer.cpp
  3. +1
    -0
      doc/samples/meshviewer.vcxproj
  4. +1
    -1
      doc/tutorial/05_easymesh.cpp
  5. +1
    -1
      doc/tutorial/14_lol_lua.cpp
  6. +1
    -0
      src/Makefile.am
  7. +1
    -1
      src/application/application.cpp
  8. +107
    -0
      src/input/controller.cpp
  9. +205
    -2
      src/input/controller.h
  10. +1
    -0
      src/lol/sys/all.h
  11. +1
    -0
      src/lol/sys/file.h
  12. +13
    -27
      src/lol/sys/thread.h
  13. +98
    -0
      src/lol/sys/threadtypes.h
  14. +2
    -0
      src/lolcore.vcxproj
  15. +6
    -0
      src/lolcore.vcxproj.filters
  16. +13
    -2
      src/lolua/baselua.cpp
  17. +6
    -5
      src/lolua/baselua.h
  18. +17
    -0
      src/sys/file.cpp
  19. +72
    -18
      src/sys/thread.cpp
  20. +62
    -0
      src/sys/threadbase.h
  21. +78
    -0
      src/sys/threadtypes.cpp

+ 2
- 5
doc/samples/Makefile.am View File

@@ -41,12 +41,9 @@ nacl_phystest_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/bullet \
nacl_phystest_DEPENDENCIES = @LOL_DEPS@
nacl_phystest_LDFLAGS = $(AM_LDFLAGS)

meshviewer_SOURCES = meshviewer.cpp \
meshviewer_SOURCES = meshviewer.cpp meshviewer.h \
shinymvtexture.lolfx shinyfur.lolfx \
scenesetup.cpp scenesetup.h \
scenesetup-compiler.cpp scenesetup-compiler.h \
generated/scenesetup-scanner.cpp generated/scenesetup-scanner.h \
generated/scenesetup-parser.cpp
scenesetup.cpp scenesetup.h
meshviewer_CPPFLAGS = $(AM_CPPFLAGS)
meshviewer_DEPENDENCIES = @LOL_DEPS@
meshviewer_LDFLAGS = $(AM_LDFLAGS)


+ 2
- 1
doc/samples/meshviewer.cpp View File

@@ -18,6 +18,7 @@

#include <lol/engine.h>
#include "scenesetup.h"
#include "meshviewer.h"

using namespace lol;

@@ -184,7 +185,7 @@ public:
m_controller = nullptr;

//Scene setup
m_setup_loader.ExecLua("meshviewer_init.lua");
m_setup_loader.ExecLuaFile("meshviewer_init.lua");

//Compile ref meshes
m_gizmos << new EasyMesh();


+ 1
- 0
doc/samples/meshviewer.vcxproj View File

@@ -91,6 +91,7 @@
<LolFxCompile Include="shinymvtexture.lolfx" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="meshviewer.h" />
<ClInclude Include="scenesetup.h" />
</ItemGroup>
<PropertyGroup Label="Globals">


+ 1
- 1
doc/tutorial/05_easymesh.cpp View File

@@ -28,7 +28,7 @@ public:
EasyMeshTutorial()
{
EasyMeshLuaLoader EzMhLoader;
EzMhLoader.ExecLua("05_easymesh.lua");
EzMhLoader.ExecLuaFile("05_easymesh.lua");

EasyMeshLuaObject* gears0 = EzMhLoader.GetPtr<EasyMeshLuaObject>("g0");
EasyMeshLuaObject* gears1 = EzMhLoader.GetPtr<EasyMeshLuaObject>("g1");


+ 1
- 1
doc/tutorial/14_lol_lua.cpp View File

@@ -152,7 +152,7 @@ public:
LoluaDemoLoader* demo_loader = new LoluaDemoLoader();

//Execute script
demo_loader->ExecLua("14_lol_lua.lua");
demo_loader->ExecLuaFile("14_lol_lua.lua");
demo_loader->TestStuff();

//Grab global test values


+ 1
- 0
src/Makefile.am View File

@@ -109,6 +109,7 @@ liblolcore_sources = \
\
sys/init.cpp sys/timer.cpp sys/file.cpp sys/hacks.cpp \
sys/thread.cpp sys/threadbase.h \
sys/threadtypes.cpp \
\
image/image.cpp image/image-private.h image/kernel.cpp image/pixel.cpp \
image/crop.cpp image/resample.cpp image/noise.cpp image/combine.cpp \


+ 1
- 1
src/application/application.cpp View File

@@ -72,7 +72,7 @@ static void AppCallback()
Application::Application(char const *name, ivec2 resolution, float framerate)
{
data = new ApplicationData(name, resolution, framerate);
g_world.ExecLua("lua/init.lua");
g_world.ExecLuaFile("lua/init.lua");
}

bool Application::MustTick()


+ 107
- 0
src/input/controller.cpp View File

@@ -225,6 +225,7 @@ float AxisBinding::RetrieveCurrentValue()

array<Controller*> Controller::controllers;

//-----------------------------------------------------------------------------
Controller::Controller(String const &name, int nb_keys, int nb_axis)
{
m_gamegroup = GAMEGROUP_BEFORE;
@@ -241,8 +242,15 @@ Controller::Controller(String const &name, int nb_keys, int nb_axis)
controllers.Push(this);
}

Controller::Controller(String const &name, InputProfile const& profile)
: Controller(name, 0, 0)
{
Init(profile);
}

Controller::~Controller()
{
ClearProfile();
for (int i = 0; i < controllers.Count(); ++i)
{
if (controllers[i] == this)
@@ -253,6 +261,7 @@ Controller::~Controller()
}
}

//-----------------------------------------------------------------------------
Controller* Controller::Get(String const &name)
{
for (int i = 0; i < controllers.Count(); ++i)
@@ -263,6 +272,102 @@ Controller* Controller::Get(String const &name)
return nullptr;
}

//Input profile system --------------------------------------------------------
void Controller::UnbindProfile()
{
if (m_profile.IsEmpty())
return;

m_mutex.lock();

//Keyboard
if (m_keyboard)
{
for (InputProfile::Keyboard& key : m_profile.m_keys)
GetKey(key.m_idx).UnbindKeyboard(key.m_name);
m_keyboard = nullptr;
}

//Mouse
if (m_mouse)
{
for (InputProfile::MouseKey& key : m_profile.m_mouse_keys)
GetKey(key.m_idx).UnbindMouse(key.m_name);
for (InputProfile::MouseAxis& axis : m_profile.m_mouse_axis)
GetAxis(axis.m_idx).UnbindMouse(axis.m_name);
m_mouse = nullptr;
}

//Joystick
for (InputProfile::JoystickKey& key : m_profile.m_joystick_keys)
{
if (m_joystick_idx.Find(key.m_joy) != INDEX_NONE)
GetKey(key.m_idx).UnbindJoystick(key.m_joy, key.m_name);
}
for (InputProfile::JoystickAxis& axis : m_profile.m_joystick_axis)
{
if (m_joystick_idx.Find(axis.m_joy) != INDEX_NONE)
GetAxis(axis.m_idx).UnbindJoystick(axis.m_joy, axis.m_name);
}
m_joystick.Empty();
m_joystick_idx.Empty();

m_mutex.unlock();
}
//Input profile system --------------------------------------------------------
void Controller::BindProfile(InputProfile const& setup)
{
ASSERT(!setup.IsEmpty());

m_mutex.lock();
m_profile = setup;

m_keys.Resize(m_profile.GetKeyCount());
m_axis.Resize(m_profile.GetAxisCount());

//Keyboard
m_keyboard = InputDevice::GetKeyboard();
if (m_keyboard)
{
for (InputProfile::Keyboard& key : m_profile.m_keys)
GetKey(key.m_idx).BindKeyboard(key.m_name);
}

//Mouse
m_mouse = InputDevice::GetMouse();
if (m_mouse)
{
for (InputProfile::MouseKey& key : m_profile.m_mouse_keys)
GetKey(key.m_idx).BindMouse(key.m_name);
for (InputProfile::MouseAxis& axis : m_profile.m_mouse_axis)
GetAxis(axis.m_idx).BindMouse(axis.m_name);
}

//Joystick
for (uint64_t joy_idx : m_profile.m_joystick)
{
class InputDevice* joystick = InputDevice::GetJoystick(joy_idx);
if (joystick)
{
m_joystick << joystick;
m_joystick_idx << joy_idx;
}
}
for (InputProfile::JoystickKey& key : m_profile.m_joystick_keys)
{
if (m_joystick_idx.Find(key.m_joy) != INDEX_NONE)
GetKey(key.m_idx).BindJoystick(key.m_joy, key.m_name);
}
for (InputProfile::JoystickAxis& axis : m_profile.m_joystick_axis)
{
if (m_joystick_idx.Find(axis.m_joy) != INDEX_NONE)
GetAxis(axis.m_idx).BindJoystick(axis.m_joy, axis.m_name);
}

m_mutex.unlock();
}

//-----------------------------------------------------------------------------
void Controller::TickGame(float seconds)
{
Entity::TickGame(seconds);
@@ -286,6 +391,7 @@ void Controller::TickGame(float seconds)
m_deactivate_nextframe = false;
}

//-----------------------------------------------------------------------------
void Controller::Activate()
{
m_activate_nextframe = true;
@@ -298,6 +404,7 @@ void Controller::Deactivate()
m_activate_nextframe = false;
}

//-----------------------------------------------------------------------------
array<Controller*> Controller::DeactivateAll()
{
array<Controller*> result;


+ 205
- 2
src/input/controller.h View File

@@ -133,11 +133,190 @@ protected:
friend class Controller;
};

//-------------------------------------------------------------------------
class InputProfile
{
friend class Controller;
private:
//---------------------------------------------------------------------
class Key
{
friend class Controller;
friend class InputProfile;
public:
Key() { }
Key(int idx, String const& name) : m_idx(idx), m_name(name) { }
Key(const Key& other) : m_idx(other.m_idx), m_name(other.m_name) { }
~Key() { }
bool operator==(const Key& other) { return m_name == other.m_name; }
private:
int m_idx = 0;
String m_name;
};
//---------------------------------------------------------------------
class Joystick
{
friend class Controller;
friend class InputProfile;
public:
Joystick() { }
Joystick(uint64_t joy, int idx, String const& name) : m_joy(joy), m_idx(idx), m_name(name) { }
Joystick(const Joystick& other) : m_joy(other.m_joy), m_idx(other.m_idx), m_name(other.m_name) { }
~Joystick() { }
bool operator==(const Joystick& other) { return m_name == other.m_name; }
private:
uint64_t m_joy = 0;
int m_idx = 0;
String m_name;
};
public:
//---------------------------------------------------------------------
class Keyboard : public Key
{
friend class Controller;
friend class InputProfile;
public:
Keyboard() : Key() { }
Keyboard(int idx, String const& name) : Key(idx, name) { }
Keyboard(const Keyboard& other) : Key(other.m_idx, other.m_name) { }
};
//---------------------------------------------------------------------
class MouseKey : public Key
{
friend class Controller;
friend class InputProfile;
public:
MouseKey() : Key() { }
MouseKey(int idx, String const& name) : Key(idx, name) { }
MouseKey(const Keyboard& other) : Key(other.m_idx, other.m_name) { }
};
//---------------------------------------------------------------------
class MouseAxis : public Key
{
friend class Controller;
friend class InputProfile;
public:
MouseAxis() : Key() { }
MouseAxis(int idx, String const& name) : Key(idx, name) { }
MouseAxis(const Keyboard& other) : Key(other.m_idx, other.m_name) { }
};
//---------------------------------------------------------------------
class JoystickKey : public Joystick
{
friend class Controller;
friend class InputProfile;
public:
JoystickKey() : Joystick() { }
JoystickKey(uint64_t joy, int idx, String const& name) : Joystick(joy, idx, name) { }
JoystickKey(const JoystickKey& other) : Joystick(other.m_joy, other.m_idx, other.m_name) { }
};
//---------------------------------------------------------------------
class JoystickAxis : public Joystick
{
friend class Controller;
friend class InputProfile;
public:
JoystickAxis() : Joystick() { }
JoystickAxis(uint64_t joy, int idx, String const& name) : Joystick(joy, idx, name) { }
JoystickAxis(const JoystickAxis& other) : Joystick(other.m_joy, other.m_idx, other.m_name) { }
};
public:
InputProfile() { }
InputProfile(const InputProfile& other)
{
m_keys = other.m_keys;
m_mouse_keys = other.m_mouse_keys;
m_mouse_axis = other.m_mouse_axis;
m_joystick = other.m_joystick;
m_joystick_keys = other.m_joystick_keys;
m_joystick_axis = other.m_joystick_axis;
}
virtual ~InputProfile() { }

bool IsEmpty() const
{
return !(GetKeyCount() && GetAxisCount());
}
int GetKeyCount() const
{
return (int)(m_keys.Count() + m_mouse_keys.Count() + m_joystick_keys.Count());
}
int GetAxisCount() const
{
return (int)(m_mouse_axis.Count() + m_joystick_axis.Count());
}
InputProfile& operator<<(InputProfile::Keyboard const& binding)
{
m_keys.PushUnique(binding);
return *this;
}
InputProfile& operator<<(array<InputProfile::Keyboard> const& bindings)
{
m_keys += bindings;
return *this;
}
InputProfile& operator<<(InputProfile::MouseKey const& binding)
{
m_mouse_keys.PushUnique(binding);
return *this;
}
InputProfile& operator<<(array<InputProfile::MouseKey> const& bindings)
{
m_mouse_keys += bindings;
return *this;
}
InputProfile& operator<<(InputProfile::MouseAxis const& binding)
{
m_mouse_axis.PushUnique(binding);
return *this;
}
InputProfile& operator<<(array<InputProfile::MouseAxis> const& bindings)
{
m_mouse_axis += bindings;
return *this;
}
InputProfile& operator<<(InputProfile::JoystickKey const& binding)
{
m_joystick.PushUnique(binding.m_joy);
m_joystick_keys.PushUnique(binding);
return *this;
}
InputProfile& operator<<(array<InputProfile::JoystickKey> const& bindings)
{
for (InputProfile::JoystickKey const& binding : bindings)
m_joystick.PushUnique(binding.m_joy);
m_joystick_keys += bindings;
return *this;
}
InputProfile& operator<<(InputProfile::JoystickAxis const& binding)
{
m_joystick.PushUnique(binding.m_joy);
m_joystick_axis.PushUnique(binding);
return *this;
}
InputProfile& operator<<(array<InputProfile::JoystickAxis> const& bindings)
{
for (InputProfile::JoystickAxis const& binding : bindings)
m_joystick.PushUnique(binding.m_joy);
m_joystick_axis += bindings;
return *this;
}

private:
array<Keyboard> m_keys;
array<MouseKey> m_mouse_keys;
array<MouseAxis> m_mouse_axis;
array<uint64_t> m_joystick;
array<JoystickKey> m_joystick_keys;
array<JoystickAxis> m_joystick_axis;
};

//-----------------------------------------------------------------------------
class Controller : public Entity
{
public:
Controller(String const &name, int nb_keys, int nb_axis);
Controller(String const &name, int nb_keys = 0, int nb_axis = 0);
Controller(String const &name, InputProfile const& setup);
virtual ~Controller();

virtual void TickGame(float seconds);
@@ -149,21 +328,45 @@ public:
/** Deactivate every active controller on next frame and return an array of deactivated (previously active) controllers */
static array<Controller*> DeactivateAll();

/** Input profile system */
void Init(InputProfile const& profile)
{
UnbindProfile();
BindProfile(profile);
}
void ClearProfile()
{
UnbindProfile();
}

/** GetKeys/Axis stuff */
KeyBinding& GetKey(int index) { return m_keys[index]; }
AxisBinding& GetAxis(int index) { return m_axis[index]; }

static Controller* Get(String const &name);

protected:
/** Input profile system */
void UnbindProfile();
void BindProfile(InputProfile const& setup);

private:
array<KeyBinding> m_keys;
array<AxisBinding> m_axis;

private:
static array<Controller*> controllers;
String m_name;
bool m_activate_nextframe;
bool m_deactivate_nextframe;
bool m_active;

//Input profile stuff
mutex m_mutex;
class InputProfile m_profile;
class InputDevice* m_keyboard = nullptr;
class InputDevice* m_mouse = nullptr;
array<class InputDevice*> m_joystick;
array<uint64_t> m_joystick_idx;
};

} /* namespace lol */


+ 1
- 0
src/lol/sys/all.h View File

@@ -11,6 +11,7 @@
#pragma once

#include <lol/sys/thread.h>
#include <lol/sys/threadtypes.h>
#include <lol/sys/init.h>
#include <lol/sys/file.h>
#include <lol/sys/timer.h>


+ 1
- 0
src/lol/sys/file.h View File

@@ -82,6 +82,7 @@ public:
long int GetPosFromStart();
void SetPosFromStart(long int pos);
long int GetSize();
long int GetModificationTime();

private:
class FileData *m_data;


+ 13
- 27
src/lol/sys/thread.h View File

@@ -38,7 +38,6 @@ public:
queue() : queue_base<T, N>() {}
};

#if LOL_FEATURE_THREADS
class thread : thread_base
{
public:
@@ -91,6 +90,7 @@ protected:
};
typedef SafeEnum<ThreadJobTypeBase> ThreadJobType;

//ThreadJob -------------------------------------------------------------------
class ThreadJob
{
friend class BaseThreadManager;
@@ -109,11 +109,12 @@ protected:
ThreadJobType m_type;
};

//Base class for thread manager
//Base class for thread manager -----------------------------------------------
class BaseThreadManager : public Entity
{
public:
BaseThreadManager(int thread_count);
BaseThreadManager(int thread_count, int thread_min);
~BaseThreadManager();

char const *GetName() { return "<BaseThreadManager>"; }
@@ -122,7 +123,16 @@ public:
bool Start();
//Stop the threads
bool Stop();

//Children class intergace
virtual bool AddJob(ThreadJob* job) { ASSERT(false); return false; }
virtual bool GetWorkResult(array<ThreadJob*>& results) { ASSERT(false); return false; }

protected:
//Thread addition
void AddThreads(int nb);
void StopThreads(int nb);

//Work stuff
bool AddWork(ThreadJob* job);

@@ -137,6 +147,7 @@ protected:

/* Worker threads */
int m_thread_count;
int m_thread_min;
array<thread*> m_threads;
queue<ThreadStatus> m_spawnqueue, m_donequeue;
queue<ThreadJob*> m_jobqueue;
@@ -144,30 +155,5 @@ protected:
array<ThreadJob*> m_job_dispatch;
};

//Generic class for thread manager, executes work and store results, for you to use
class GenericThreadManager : public BaseThreadManager
{
public:
GenericThreadManager(int thread_count)
: BaseThreadManager(thread_count) { }

char const *GetName() { return "<GenericThreadManager>"; }

//Work stuff
bool AddJob(ThreadJob* job) { return AddWork(job); }
bool GetWorkResult(array<ThreadJob*>& results)
{
results += m_job_result;
m_job_result.Empty();
return results.Count() > 0;
}

protected:
virtual void TreatResult(ThreadJob* result) { m_job_result << result; }

array<ThreadJob*> m_job_result;
};
#endif

} /* namespace lol */


+ 98
- 0
src/lol/sys/threadtypes.h View File

@@ -0,0 +1,98 @@
//
// Lol Engine
//
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
// © 2013—2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
//
// This library is free software. It comes without any warranty, to
// the extent permitted by applicable law. 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 the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#pragma once

//
// The Threading classes
// ---------------------
//

namespace lol
{

//Generic class for thread manager, executes work and store results, with no specific treatment
class DefaultThreadManager : public BaseThreadManager
{
public:
DefaultThreadManager(int thread_count)
: DefaultThreadManager(thread_count, thread_count)
{ }
DefaultThreadManager(int thread_count, int thread_min)
: DefaultThreadManager(thread_count, thread_min)
{ }

char const *GetName() { return "<DefaultThreadManager>"; }

//Work stuff
bool AddJob(ThreadJob* job);
bool GetWorkResult(array<ThreadJob*>& results);

protected:
virtual void TreatResult(ThreadJob* result) { m_job_result << result; }
array<ThreadJob*> m_job_result;
};

//FileUpdateTesterJob ---------------------------------------------------------
class FileUpdateTesterJob : public ThreadJob
{
public:
FileUpdateTesterJob()
: ThreadJob(ThreadJobType::NONE) { }
FileUpdateTesterJob(String path)
: ThreadJob(ThreadJobType::WORK_TODO)
{ m_path = path; }
String& GetPath() { return m_path; }
bool HasUpdated() { return m_updated; }
void Restart()
{
SetJobType(ThreadJobType::WORK_TODO);
m_updated = false;
}

protected:
virtual bool DoWork();

//-----------------
bool m_ready = false;
String m_path = String();
long int m_time = 0;
bool m_updated = false;
};

//Test the files registered and warns when they update ------------------------
class FileUpdateTester : public BaseThreadManager
{
typedef BaseThreadManager super;
public:
struct Status
{
bool m_updated = false;
};
public:
FileUpdateTester() : BaseThreadManager(1) { }
~FileUpdateTester() { }
char const *GetName() { return "<FileUpdateTester>"; }

//-------------------------------------------------------------------------
FileUpdateTester::Status* RegisterFile(String const& path);
virtual void TickGame(float seconds);
virtual void TreatResult(ThreadJob* result);

private:
array<ThreadJob*> m_job_done;
map<String, Status*> m_files;
};

} /* namespace lol */


+ 2
- 0
src/lolcore.vcxproj View File

@@ -222,6 +222,7 @@
<ClCompile Include="sys\hacks.cpp" />
<ClCompile Include="sys\init.cpp" />
<ClCompile Include="sys\thread.cpp" />
<ClCompile Include="sys\threadtypes.cpp" />
<ClCompile Include="sys\timer.cpp" />
<ClCompile Include="text.cpp" />
<ClCompile Include="ticker.cpp" />
@@ -319,6 +320,7 @@
<ClInclude Include="lol\sys\file.h" />
<ClInclude Include="lol\sys\init.h" />
<ClInclude Include="lol\sys\thread.h" />
<ClInclude Include="lol\sys\threadtypes.h" />
<ClInclude Include="lol\sys\timer.h" />
<ClInclude Include="lol\unit.h" />
<ClInclude Include="mesh\mesh.h" />


+ 6
- 0
src/lolcore.vcxproj.filters View File

@@ -412,6 +412,9 @@
<ClCompile Include="lolua\baselua.cpp">
<Filter>lolua</Filter>
</ClCompile>
<ClCompile Include="sys\threadtypes.cpp">
<Filter>sys</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="debug\fps.h">
@@ -769,6 +772,9 @@
<ClInclude Include="lolua\baselua.h">
<Filter>lolua</Filter>
</ClInclude>
<ClInclude Include="lol\sys\threadtypes.h">
<Filter>lol\sys</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<LolFxCompile Include="gpu\emptymaterial.lolfx">


+ 13
- 2
src/lolua/baselua.cpp View File

@@ -33,6 +33,11 @@ class LuaBaseData
return 0;
}

static int LuaDoCode(LuaState *l, String const& s)
{
return luaL_dostring(l, s.C());
}

static int LuaDoFile(LuaState *l)
{
if (lua_isnoneornil(l, 1))
@@ -53,7 +58,7 @@ class LuaBaseData
f.Close();

Log::Debug("loading Lua file %s\n", pathlist[i].C());
status = luaL_dostring(l, s.C());
status = LuaDoCode(l, s);
break;
}
}
@@ -94,13 +99,19 @@ Loader::~Loader()
}

//-----------------------------------------------------------------------------
bool Loader::ExecLua(String const &lua)
bool Loader::ExecLuaFile(String const &lua)
{
const char* c = lua_pushstring(m_lua_state, lua.C());
int status = LuaBaseData::LuaDoFile(m_lua_state);
return status == 0;
}

//-----------------------------------------------------------------------------
bool Loader::ExecLuaCode(String const &lua)
{
return 0 == LuaBaseData::LuaDoCode(m_lua_state, lua);
}

//-----------------------------------------------------------------------------
LuaState* Loader::GetLuaState()
{


+ 6
- 5
src/lolua/baselua.h View File

@@ -54,9 +54,9 @@ struct ObjectLib
} ClassVarStr;

ObjectLib(String class_name,
array<ClassMethod> statics,
array<ClassMethod> methods,
array<ClassVar> variables)
array<ClassMethod> const& statics,
array<ClassMethod> const& methods,
array<ClassVar> const& variables)
{
m_class_name = class_name;
m_static_name = class_name + "_lib";
@@ -74,7 +74,7 @@ struct ObjectLib
|| m_methods.Last().func != nullptr)
m_methods.Push({ nullptr, nullptr });

for (ClassVar& cv : variables)
for (ClassVar const& cv : variables)
{
if (cv.name && cv.get && cv.set)
{
@@ -934,7 +934,8 @@ public:
Loader();
virtual ~Loader();

bool ExecLua(String const &lua);
bool ExecLuaFile(String const &lua);
bool ExecLuaCode(String const &lua);

template<typename T>
T GetVar(String const &name)


+ 17
- 0
src/sys/file.cpp View File

@@ -192,7 +192,18 @@ class FileData
#endif
}

long int GetModificationTime()
{
#if __ANDROID__
return 0;
#elif HAVE_STDIO_H
return m_stat.st_mtime;
#else
return 0;
#endif
}

//-----------------------
#if __ANDROID__
AAsset *m_asset;
#elif HAVE_STDIO_H
@@ -314,6 +325,12 @@ long int File::GetSize()
return m_data->GetSize();
}

//--
long int File::GetModificationTime()
{
return m_data->GetModificationTime();
}

//---------------
class DirectoryData
{


+ 72
- 18
src/sys/thread.cpp View File

@@ -16,9 +16,16 @@
namespace lol
{

#if LOL_FEATURE_THREADS
//BaseThreadManager -----------------------------------------------------------
BaseThreadManager::BaseThreadManager(int thread_count)
{
m_thread_min = thread_count;
m_thread_count = thread_count;
}

BaseThreadManager::BaseThreadManager(int thread_min, int thread_count)
{
m_thread_min = thread_min;
m_thread_count = thread_count;
}

@@ -30,16 +37,12 @@ BaseThreadManager::~BaseThreadManager()
//Initialize, Ticker::Ref and start the thread
bool BaseThreadManager::Start()
{
if (m_threads.Count() > 0)
if (m_threads.count() > 0)
return false;

/* Spawn worker threads and wait for their readiness. */
//Add minimum threads
m_threads.Resize(m_thread_count);
for (int i = 0; i < m_thread_count; i++)
m_threads[i] = new thread(std::bind(&BaseThreadManager::BaseThreadWork,
this));
for (int i = 0; i < m_thread_count; i++)
m_spawnqueue.pop();
AddThreads(m_thread_min);

return true;
}
@@ -47,18 +50,44 @@ bool BaseThreadManager::Start()
//Stop the threads
bool BaseThreadManager::Stop()
{
if (m_threads.Count() <= 0)
if (m_threads.count() <= 0)
return false;

/* Signal worker threads for completion and wait for
* them to quit. */
ThreadJob stop_job(ThreadJobType::THREAD_STOP);
//Stop all threads
StopThreads(m_threads.count());

return true;
}

//----
void BaseThreadManager::AddThreads(int nb)
{
//Don't add threads if not availables
#if LOL_FEATURE_THREADS
//Spawn worker threads and ...
for (int i = 0; i < nb; i++)
m_threads << new thread(std::bind(&BaseThreadManager::BaseThreadWork, this));

//... Wait for their readiness.
for (int i = 0; i < m_thread_count; i++)
m_spawnqueue.pop();
#endif //LOL_FEATURE_THREADS
}

//----
void BaseThreadManager::StopThreads(int nb)
{
//Don't stop threads if not availables
#if LOL_FEATURE_THREADS
//Signal worker threads for completion and ...
ThreadJob stop_job(ThreadJobType::THREAD_STOP);
for (int i = 0; i < nb; i++)
m_jobqueue.push(&stop_job);
for (int i = 0; i < m_thread_count; i++)
//... Wait for them to quit.
for (int i = 0; i < nb; i++)
m_donequeue.pop();

return true;
#endif //LOL_FEATURE_THREADS
}

//Work stuff
@@ -69,23 +98,34 @@ bool BaseThreadManager::AddWork(ThreadJob* job)
return false;
}

//----
bool BaseThreadManager::FetchResult(array<ThreadJob*>& results)
{
ThreadJob* result;
while (m_resultqueue.try_pop(result))
results << result;
return results.Count() > 0;
return results.count() > 0;
}

//Base thread work function
void BaseThreadManager::BaseThreadWork()
{
#if !LOL_FEATURE_THREADS
//Register that the thread has started
m_spawnqueue.push(ThreadStatus::THREAD_STARTED);
for ( ; ; )
#endif //!LOL_FEATURE_THREADS
{
//Try to retrieve a job
ThreadJob* job = m_jobqueue.pop();
//Stop thread
if (job->GetJobType() == ThreadJobType::THREAD_STOP)
{
#if !LOL_FEATURE_THREADS
break;
#endif //!LOL_FEATURE_THREADS
}
//Or work
else if (*job == ThreadJobType::WORK_TODO)
{
if (job->DoWork())
@@ -95,9 +135,13 @@ void BaseThreadManager::BaseThreadWork()
m_resultqueue.push(job);
}
}
#if !LOL_FEATURE_THREADS
//Register that the thread has stopped
m_donequeue.push(ThreadStatus::THREAD_STOPPED);
#endif //!LOL_FEATURE_THREADS
}

//----
void BaseThreadManager::TickGame(float seconds)
{
Entity::TickGame(seconds);
@@ -109,11 +153,16 @@ void BaseThreadManager::TickGame(float seconds)
while (m_job_dispatch.Count() > 0 && AddWork(m_job_dispatch.Last()))
m_job_dispatch.pop();

//Execute one task per frame if thread are not available
#if !LOL_FEATURE_THREADS
BaseThreadWork();
#endif // !LOL_FEATURE_THREADS

array<ThreadJob*> result;
//Fetch and treat results
if (FetchResult(result))
{
for (int i = 0; i < result.Count(); i++)
for (int i = 0; i < result.count(); i++)
{
ThreadJob* job = result[i];
if (job->GetJobType() == ThreadJobType::WORK_DONE)
@@ -123,7 +172,12 @@ void BaseThreadManager::TickGame(float seconds)
}
}
}

//Resize thread count if needed
if (m_threads.count() > m_jobqueue.count() && m_threads.count() > m_thread_min)
StopThreads(m_threads.Count() - m_thread_min);
else if (m_threads.count() < m_jobqueue.count())
AddThreads(lol::min(m_jobqueue.count(), (ptrdiff_t)m_thread_count) - m_threads.count());
}
#endif //LOL_FEATURE_THREADS

} /* namespace lol */

+ 62
- 0
src/sys/threadbase.h View File

@@ -114,6 +114,68 @@ public:
#endif
}

ptrdiff_t count()
{
ptrdiff_t current_count = 0;
#if defined HAVE_PTHREAD_H
pthread_mutex_lock(&m_mutex);
/* If queue is full, wait on the "full" cond var. */
m_pushers++;
while (m_count == CAPACITY)
pthread_cond_wait(&m_full_cond, &m_mutex);
m_pushers--;
#elif defined _WIN32
WaitForSingleObject(m_empty_sem, INFINITE);
EnterCriticalSection(&m_mutex);
#endif

current_count = (ptrdiff_t)m_count;

#if defined HAVE_PTHREAD_H
/* If there were poppers waiting, signal the "empty" cond var. */
if (m_poppers)
pthread_cond_signal(&m_empty_cond);
pthread_mutex_unlock(&m_mutex);
#elif defined _WIN32
LeaveCriticalSection(&m_mutex);
ReleaseSemaphore(m_full_sem, 1, nullptr);
#endif
return current_count;
}

ptrdiff_t try_count()
{
ptrdiff_t current_count = 0;

#if defined HAVE_PTHREAD_H
pthread_mutex_lock(&m_mutex);
/* If queue is full, wait on the "full" cond var. */
if (m_count == CAPACITY)
{
pthread_mutex_unlock(&m_mutex);
return false;
}
#elif defined _WIN32
DWORD status = WaitForSingleObject(m_empty_sem, 0);
if (status == WAIT_TIMEOUT)
return 0;
EnterCriticalSection(&m_mutex);
#endif

current_count = (ptrdiff_t)m_count;

#if defined HAVE_PTHREAD_H
/* If there were poppers waiting, signal the "empty" cond var. */
if (m_poppers)
pthread_cond_signal(&m_empty_cond);
pthread_mutex_unlock(&m_mutex);
#elif defined _WIN32
LeaveCriticalSection(&m_mutex);
ReleaseSemaphore(m_full_sem, 1, nullptr);
#endif
return current_count;
}

void push(T value)
{
#if defined HAVE_PTHREAD_H


+ 78
- 0
src/sys/threadtypes.cpp View File

@@ -0,0 +1,78 @@
//
// Lol Engine
//
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
// © 2014—2015 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
//
// This library is free software. It comes without any warranty, to
// the extent permitted by applicable law. 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 the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#include <lol/engine-internal.h>

using namespace lol;

//DefaultThreadManager --------------------------------------------------------
bool DefaultThreadManager::AddJob(ThreadJob* job)
{
return AddWork(job);
}
bool DefaultThreadManager::GetWorkResult(array<ThreadJob*>& results)
{
results += m_job_result;
m_job_result.Empty();
return results.Count() > 0;
}

//FileUpdateTesterJob ---------------------------------------------------------
bool FileUpdateTesterJob::DoWork()
{
File f;
f.Open(m_path, FileAccess::Read);
if (!f.IsValid())
return false;
if (!m_ready)
m_time = f.GetModificationTime();
else
{
long int new_time = f.GetModificationTime();
if (new_time > m_time)
m_updated = true;
}
return true;
}

//FileUpdateTester ------------------------------------------------------------
FileUpdateTester::Status* FileUpdateTester::RegisterFile(String const& path)
{
m_job_dispatch << new FileUpdateTesterJob(path);
m_files[path] = new FileUpdateTester::Status();
return m_files[path];
}

//-------------------------------------------------------------------------
void FileUpdateTester::TickGame(float seconds)
{
super::TickGame(seconds);

if (!m_job_dispatch.count() && m_job_done.count())
{
m_job_dispatch = m_job_done;
m_job_done.empty();
}
}

//-------------------------------------------------------------------------
void FileUpdateTester::TreatResult(ThreadJob* result)
{
FileUpdateTesterJob* job = static_cast<FileUpdateTesterJob*>(result);
if (job->HasUpdated())
{
m_files[job->GetPath()]->m_updated = true;
job->Restart();
m_job_done << job;
}
}

Loading…
Cancel
Save