From c9b7f21be5fca9199634f921dbc0c5f905b10f79 Mon Sep 17 00:00:00 2001 From: Vladislav Khorev Date: Sun, 3 Feb 2013 13:11:16 +0000 Subject: [PATCH] --- Salmon Engine/Salmon Engine.vcxproj | 3 ++ include/SalmonEngineInterface.h | 11 ++++- include/SalmonEngineWindows.h | 2 + include/TextureManager/SalmonTexture.h | 7 ++- include/Utils/ThreadUtils.h | 36 ++++++++++++++ include/Utils/ThreadUtilsImpl.h | 65 ++++++++++++++++++++++++++ include/Utils/Utils.h | 1 + src/ApplicationInterface.cpp | 2 + src/SalmonEngineInterface.cpp | 44 +++++++++++++++-- src/TextureManager/SalmonTexture.cpp | 44 ++++++++++++++--- src/Utils/ThreadUtils.cpp | 26 +++++++++++ 11 files changed, 228 insertions(+), 13 deletions(-) create mode 100644 include/Utils/ThreadUtils.h create mode 100644 include/Utils/ThreadUtilsImpl.h create mode 100644 src/Utils/ThreadUtils.cpp 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