diff --git a/Salmon Engine/Salmon Engine.vcxproj b/Salmon Engine/Salmon Engine.vcxproj
index fd9a1a7..c01b1b5 100644
--- a/Salmon Engine/Salmon Engine.vcxproj
+++ b/Salmon Engine/Salmon Engine.vcxproj
@@ -55,6 +55,8 @@
+
+
@@ -96,6 +98,7 @@
+
diff --git a/include/SalmonEngineInterface.h b/include/SalmonEngineInterface.h
index b4373b7..af33af0 100644
--- a/include/SalmonEngineInterface.h
+++ b/include/SalmonEngineInterface.h
@@ -56,6 +56,13 @@ protected:
public:
std::string PathToResources;
+ boost::thread::id MainThreadId;
+
+ std::vector> MainThreadAsyncFunctionArr;
+
+ boost::mutex FuncListMutex;
+ std::list MainThreadSyncFunctionList;
+
TTextureListClass TexList;
TModelManager ModelManager;
TFlexModelManager FlexModelManager;
@@ -79,7 +86,9 @@ public:
TSoundManagerIos SoundManager;
#endif
- ~TResourceManager() { }
+ void Update(cardinal timer);
+
+ ~TResourceManager();
};
diff --git a/include/SalmonEngineWindows.h b/include/SalmonEngineWindows.h
index fb8a295..cec4f2d 100644
--- a/include/SalmonEngineWindows.h
+++ b/include/SalmonEngineWindows.h
@@ -65,4 +65,6 @@ int MainLoop(TApplication& application);
//This file includes templates that call any of three singletones: Console, ResourceManager or Renderer
#include "include/GUIManager/WidgetTemplatesImpl.h"
+#include "include/Utils/ThreadUtilsImpl.h"
+
diff --git a/include/TextureManager/SalmonTexture.h b/include/TextureManager/SalmonTexture.h
index ff519a5..ca62f55 100644
--- a/include/TextureManager/SalmonTexture.h
+++ b/include/TextureManager/SalmonTexture.h
@@ -58,12 +58,14 @@ protected:
bool CreateTexDataFromBmp32(const std::string& filename, TTextureData& texData);
bool CreateTexDataFromTga(const std::string& filename, TTextureData& texData);
bool CreateTexDataFromPng(const std::string& filename, TTextureData& texData);
+
cardinal AddTextureBmp24Data(const TTextureData& texData);
cardinal AddTextureBmp32Data(const TTextureData& texData);
-
cardinal AddCubemapTextureBmp24Data(TTextureData* texData);
//cardinal AddCubemapTextureBmp32Data(TTextureData* texData); Not implemented yet
+ void InnerClear();
+
public:
TTextureListClass();
~TTextureListClass();
@@ -84,7 +86,8 @@ public:
cardinal GetTextureWidth(const std::string& texName);
cardinal AddTextureDirectly(const std::string& filename, std::string texName = ""); //Loads texture directly from this file or fails
- cardinal AddTexture(const std::string& fileName, std::string texName = ""); //Adds path to resources to the filename then call previous one
+ cardinal AddTexture(const std::string& fileName);
+ cardinal AddTexture(const std::string& fileName, std::string texName); //Adds path to resources to the filename then call previous one
cardinal AddTextureFromUserdata(const std::string& fileName, std::string texName = ""); //Same as above but checks if file is created in user data
cardinal AddCubemapTexture(std::string filename[6]); // "posx.bmp","negx.bmp","posy.bmp","negy.bmp","posz.bmp","negz.bmp"
diff --git a/include/Utils/ThreadUtils.h b/include/Utils/ThreadUtils.h
new file mode 100644
index 0000000..c8db689
--- /dev/null
+++ b/include/Utils/ThreadUtils.h
@@ -0,0 +1,36 @@
+#ifndef THREAD_UTILS_H_INCLUDED
+#define THREAD_UTILS_H_INCLUDED
+
+#include "boost/signal.hpp"
+#include "boost/thread.hpp"
+
+
+namespace SE
+{
+
+ struct TFuncToPerform
+ {
+ private:
+ public:
+
+ TFuncToPerform()
+ : LockerPtr(new boost::mutex)
+ {
+ }
+
+ bool Executed;
+
+ std::shared_ptr LockerPtr;
+
+ boost::function Func;
+ };
+
+ void AssertIfInMainThread();
+ void PerformInMainThreadAsync(boost::function f);
+
+ template
+ RETURNTYPE PerformInMainThread(boost::function f);
+
+} //namespace SE
+
+#endif
\ No newline at end of file
diff --git a/include/Utils/ThreadUtilsImpl.h b/include/Utils/ThreadUtilsImpl.h
new file mode 100644
index 0000000..43bf316
--- /dev/null
+++ b/include/Utils/ThreadUtilsImpl.h
@@ -0,0 +1,65 @@
+#ifndef THREAD_UTILS_IMPL_H_INCLUDED
+#define THREAD_UTILS_IMPL_H_INCLUDED
+
+#include "include/Engine.h"
+
+
+namespace SE
+{
+
+ template
+ struct TCoverFunc
+ {
+ public:
+ typedef void result_type;
+
+ boost::function Func;
+
+ void operator()(RETURNTYPE& rx)
+ {
+ rx = Func();
+ }
+ };
+
+ template
+ RETURNTYPE PerformInMainThread(boost::function f)
+ {
+
+ if (boost::this_thread::get_id() == ResourceManager->MainThreadId)
+ {
+ return f();
+ }
+ else
+ {
+ RETURNTYPE result;
+
+ TCoverFunc cover_f;
+
+ cover_f.Func = f;
+
+ TFuncToPerform funcToPerform;
+
+ funcToPerform.Executed = false;
+ funcToPerform.Func = boost::bind(cover_f, boost::ref(result));
+ funcToPerform.LockerPtr->lock();
+
+ ResourceManager->FuncListMutex.lock();
+ auto itr = ResourceManager->MainThreadSyncFunctionList.insert(ResourceManager->MainThreadSyncFunctionList.end(), funcToPerform);
+ ResourceManager->FuncListMutex.unlock();
+
+ itr->LockerPtr->lock(); //wait until lock will be released
+ itr->LockerPtr->unlock();
+
+ ResourceManager->FuncListMutex.lock();
+ ResourceManager->MainThreadSyncFunctionList.erase(itr);
+ ResourceManager->FuncListMutex.unlock();
+
+
+ return result;
+
+ }
+ }
+
+} //namespace SE
+
+#endif
\ No newline at end of file
diff --git a/include/Utils/Utils.h b/include/Utils/Utils.h
index c50964c..4b2e011 100644
--- a/include/Utils/Utils.h
+++ b/include/Utils/Utils.h
@@ -25,6 +25,7 @@ This code combines additional routines (such as console/log, exceptions, math ut
#include "include/Utils/BindableVar.h"
#include "include/Utils/SimpleTimer.h"
+#include "include/Utils/ThreadUtils.h"
#ifdef TARGET_WIN32
#include "WinApi/WinApi.h"
diff --git a/src/ApplicationInterface.cpp b/src/ApplicationInterface.cpp
index 925b27b..1cea9b9 100644
--- a/src/ApplicationInterface.cpp
+++ b/src/ApplicationInterface.cpp
@@ -11,6 +11,8 @@ TApplicationInterface::TApplicationInterface()
void TApplicationInterface::OuterInit(int screenWidth, int screenHeight, float matrixWidth, float matrixHeight)
{
+ ResourceManager->MainThreadId = boost::this_thread::get_id();
+
ResourceManager->ScriptManager.BindBasicFunctions();
Renderer->InitOpenGL(screenWidth, screenHeight, matrixWidth, matrixHeight);
diff --git a/src/SalmonEngineInterface.cpp b/src/SalmonEngineInterface.cpp
index 9d5cb8e..89341ad 100644
--- a/src/SalmonEngineInterface.cpp
+++ b/src/SalmonEngineInterface.cpp
@@ -21,6 +21,46 @@ TSalmonRendererIos* Renderer;
TResourceManager* ResourceManager;
+
+void TResourceManager::Update(cardinal timer)
+{
+
+ FuncListMutex.lock();
+
+ SoundManager.Update(timer);
+
+ GUIManager.Update(timer);
+
+ if (MainThreadAsyncFunctionArr.size() != 0)
+ {
+ MainThreadAsyncFunctionArr[0]();
+
+ MainThreadAsyncFunctionArr.erase(MainThreadAsyncFunctionArr.begin());
+ }
+
+ auto itr = MainThreadSyncFunctionList.begin();
+
+ while (itr != MainThreadSyncFunctionList.end() && itr->Executed)
+ {
+ itr++;
+ }
+
+ if (itr != MainThreadSyncFunctionList.end())
+ {
+ itr->Func();
+ itr->Executed = true;
+ itr->LockerPtr->unlock();
+ }
+
+ FuncListMutex.unlock();
+}
+
+TResourceManager::~TResourceManager()
+{
+
+}
+
+
TApplicationAncestor::TApplicationAncestor()
{
@@ -63,9 +103,7 @@ void TApplicationAncestor::OuterDraw()
void TApplicationAncestor::OuterUpdate(cardinal timer)
{
- ResourceManager->SoundManager.Update(timer);
-
- ResourceManager->GUIManager.Update(timer);
+ ResourceManager->Update(timer);
InnerUpdate(timer);
diff --git a/src/TextureManager/SalmonTexture.cpp b/src/TextureManager/SalmonTexture.cpp
index 803e95c..13ee99d 100644
--- a/src/TextureManager/SalmonTexture.cpp
+++ b/src/TextureManager/SalmonTexture.cpp
@@ -37,6 +37,13 @@ TTextureListClass::~TTextureListClass()
void TTextureListClass::Clear()
{
+ PerformInMainThreadAsync(boost::bind(&TTextureListClass::InnerClear, this));
+}
+
+void TTextureListClass::InnerClear()
+{
+
+ AssertIfInMainThread();
if (TexMap.size() != 0)
{
@@ -50,7 +57,6 @@ void TTextureListClass::Clear()
*Console<<"ResourceManager::TexList cleared";
}
-
}
void TTextureListClass::Serialize(boost::property_tree::ptree& propertyTree)
@@ -397,7 +403,7 @@ bool TTextureListClass::CreateTexDataFromPng(const std::string& filename, TTextu
cardinal TTextureListClass::AddTextureBmp24Data(const TTextureData& texData)
{
-
+ AssertIfInMainThread();
cardinal TexID = 0;
@@ -424,6 +430,8 @@ cardinal TTextureListClass::AddTextureBmp24Data(const TTextureData& texData)
cardinal TTextureListClass::AddTextureBmp32Data(const TTextureData& texData)
{
+ AssertIfInMainThread();
+
cardinal TexID;
glGenTextures(1, &TexID);
if (TexID == 0)
@@ -448,6 +456,8 @@ cardinal TTextureListClass::AddTextureBmp32Data(const TTextureData& texData)
cardinal TTextureListClass::AddCubemapTextureBmp24Data(TTextureData* texData)
{
+ AssertIfInMainThread();
+
cardinal TexID;
glGenTextures(1, &TexID);
glBindTexture(GL_TEXTURE_CUBE_MAP, TexID);
@@ -492,6 +502,7 @@ cardinal TTextureListClass::GetTextureWidth(const std::string& texName)
cardinal TTextureListClass::AddTextureDirectly(const std::string& filename, std::string texName)
{
+ AssertIfInMainThread();
cardinal TexID;
@@ -545,12 +556,18 @@ cardinal TTextureListClass::AddTextureDirectly(const std::string& filename, std:
}
+cardinal TTextureListClass::AddTexture(const std::string& fileName)
+{
+ return AddTexture(fileName, "");
+}
+
cardinal TTextureListClass::AddTexture(const std::string& fileName, std::string texName)
{
-
std::string fullFileName = ResourceManager->PathToResources + fileName;
- return AddTextureDirectly(fullFileName, texName);
-
+
+ boost::function f = boost::bind(&TTextureListClass::AddTextureDirectly, this, fullFileName, texName);
+
+ return PerformInMainThread(f);
}
@@ -565,13 +582,16 @@ cardinal TTextureListClass::AddTextureFromUserdata(const std::string& fileName,
std::string fullFileName = GetFilePathUserData(fileName);
- return AddTextureDirectly(fullFileName.c_str(), texName);
+
+ boost::function f = boost::bind(&TTextureListClass::AddTextureDirectly, this, fullFileName, texName);
+
+ return PerformInMainThread(f);
}
cardinal TTextureListClass::AddCubemapTexture(std::string filename[6])
{
-
+ AssertIfInMainThread();
filename[0] = ResourceManager->PathToResources + filename[0];
filename[1] = ResourceManager->PathToResources + filename[1];
@@ -643,6 +663,8 @@ cardinal TTextureListClass::AddCubemapTexture(std::string filename[6])
cardinal TTextureListClass::AddEmptyTexture(const std::string& texName,cardinal width,cardinal height)
{
+ AssertIfInMainThread();
+
cardinal texID;
if (TexMap.count(texName) == 0)
@@ -680,6 +702,8 @@ cardinal TTextureListClass::AddEmptyTexture(const std::string& texName,cardinal
cardinal TTextureListClass::AddEmptyCubemapTexture(const std::string& texName,cardinal width,cardinal height)
{
+ AssertIfInMainThread();
+
cardinal texID;
if (TexMap.count(texName) == 0)
@@ -734,6 +758,8 @@ cardinal TTextureListClass::AddEmptyCubemapTexture(const std::string& texName,ca
cardinal TTextureListClass::AddDepthTexture(const std::string& texName,cardinal width,cardinal height)
{
+ AssertIfInMainThread();
+
#ifdef TARGET_WIN32
cardinal texID;
@@ -783,6 +809,8 @@ cardinal TTextureListClass::AddDepthTexture(const std::string& texName,cardinal
void TTextureListClass::DeleteTexture(const std::string& texName)
{
+ AssertIfInMainThread();
+
if (TexMap.count(texName) != 0)
{
--TexMap[texName].RefCount;
@@ -801,6 +829,8 @@ void TTextureListClass::DeleteTexture(const std::string& texName)
void TTextureListClass::DeleteTexture(cardinal texID)
{
+ AssertIfInMainThread();
+
TTextureMap::iterator i = TexMap.begin();
while (i != TexMap.end())
diff --git a/src/Utils/ThreadUtils.cpp b/src/Utils/ThreadUtils.cpp
new file mode 100644
index 0000000..cf328f5
--- /dev/null
+++ b/src/Utils/ThreadUtils.cpp
@@ -0,0 +1,26 @@
+#include "include/Engine.h"
+
+namespace SE
+{
+
+ void AssertIfInMainThread()
+ {
+ if (boost::this_thread::get_id() != ResourceManager->MainThreadId)
+ {
+ throw ErrorToLog("ERROR! AssertIfInMainThread failed!");
+ }
+ }
+
+ void PerformInMainThreadAsync(boost::function f)
+ {
+ if (boost::this_thread::get_id() == ResourceManager->MainThreadId)
+ {
+ f();
+ }
+ else
+ {
+ ResourceManager->MainThreadAsyncFunctionArr.push_back(f);
+ }
+ }
+
+} //namespace SE
\ No newline at end of file