diff --git a/src/scripts/CMakeLists.txt b/src/scripts/CMakeLists.txt index 33459e24..b68c3c0b 100644 --- a/src/scripts/CMakeLists.txt +++ b/src/scripts/CMakeLists.txt @@ -5,7 +5,8 @@ file(GLOB SCRIPT_INCLUDE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/*.h") message("exec: ${EXECUTABLE_OUTPUT_PATH}") -set(SCRIPT_LIB_DIR "${EXECUTABLE_OUTPUT_PATH}/compiledscripts/" ) +set(SCRIPT_POSTBUILD_DIR "${EXECUTABLE_OUTPUT_PATH}/compiledscripts/") +set(SCRIPT_LIB_DIR "${EXECUTABLE_OUTPUT_PATH}/tmp/compiledscripts/" ) set(EXECUTABLE_OUTPUT_PATH "${SCRIPT_LIB_DIR}") set(LIBRARY_OUTPUT_PATH "${SCRIPT_LIB_DIR}") set(RUNTIME_OUTPUT_DIRECTORY "${SCRIPT_LIB_DIR}") @@ -55,15 +56,27 @@ foreach(_scriptDir ${children}) configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.cpp.in" "${_scriptDir}/ScriptLoader.cpp") + set(ScriptTargetName "script_${_name}") + # Copy the modules over once they're built. Prevent watchdog from trying to reload partially written files. if(MSVC) add_custom_command(TARGET "script_${_name}" POST_BUILD COMMAND ${CMAKE_COMMAND} -E remove "${SCRIPT_LIB_DIR}/script_${_name}.exp" COMMAND ${CMAKE_COMMAND} -E remove "${SCRIPT_LIB_DIR}/script_${_name}.lib" COMMAND ${CMAKE_COMMAND} -E remove "${SCRIPT_LIB_DIR}/script_${_name}.ilk" + COMMAND ${CMAKE_COMMAND} -E copy "${SCRIPT_LIB_DIR}/script_${_name}.dll" ${SCRIPT_POSTBUILD_DIR}${ScriptTargetName}.dll_LOCK + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${SCRIPT_LIB_DIR}/script_${_name}.dll" ${SCRIPT_POSTBUILD_DIR}${ScriptTargetName}.dll + COMMAND ${CMAKE_COMMAND} -E remove ${SCRIPT_POSTBUILD_DIR}${ScriptTargetName}.dll_LOCK + ) + else() + add_custom_command(TARGET "script_${_name}" POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${SCRIPT_POSTBUILD_DIR}_LOCK + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${SCRIPT_POSTBUILD_DIR} + COMMAND ${CMAKE_COMMAND} -E remove ${SCRIPT_POSTBUILD_DIR}$_LOCK ) endif() + unset(ScriptTargetName) unset(ScriptIncludes) unset(ScriptNames) endif() diff --git a/src/world/Script/NativeScriptMgr.cpp b/src/world/Script/NativeScriptMgr.cpp index e932c0f7..9ce22785 100644 --- a/src/world/Script/NativeScriptMgr.cpp +++ b/src/world/Script/NativeScriptMgr.cpp @@ -9,6 +9,8 @@ namespace Sapphire::Scripting bool NativeScriptMgr::loadScript( const std::string& path ) { + std::scoped_lock lock( m_mutex ); + auto module = m_loader.loadModule( path ); if( !module ) return false; @@ -47,11 +49,15 @@ namespace Sapphire::Scripting const std::string NativeScriptMgr::getModuleExtension() { + std::scoped_lock lock( m_mutex ); + return m_loader.getModuleExtension(); } bool NativeScriptMgr::unloadScript( const std::string& name ) { + std::scoped_lock lock( m_mutex ); + auto info = m_loader.getScriptInfo( name ); if( !info ) return false; @@ -61,6 +67,8 @@ namespace Sapphire::Scripting bool NativeScriptMgr::unloadScript( ScriptInfo* info ) { + std::scoped_lock lock( m_mutex ); + for( auto& script : info->scripts ) { m_scripts[ script->getType() ].erase( script->getId() ); @@ -83,11 +91,14 @@ namespace Sapphire::Scripting if( !unloadScript( info ) ) return; + std::scoped_lock lock( m_mutex ); m_scriptLoadQueue.push( libPath ); } void NativeScriptMgr::processLoadQueue() { + std::scoped_lock lock( m_mutex ); + std::vector< std::string > deferredLoads; while( !m_scriptLoadQueue.empty() ) @@ -110,11 +121,15 @@ namespace Sapphire::Scripting void NativeScriptMgr::findScripts( std::set< Sapphire::Scripting::ScriptInfo* >& scripts, const std::string& search ) { + std::scoped_lock lock( m_mutex ); + return m_loader.findScripts( scripts, search ); } bool NativeScriptMgr::isModuleLoaded( const std::string& name ) { + std::scoped_lock lock( m_mutex ); + return m_loader.isModuleLoaded( name ); } diff --git a/src/world/Script/NativeScriptMgr.h b/src/world/Script/NativeScriptMgr.h index 668408a0..d7c56c40 100644 --- a/src/world/Script/NativeScriptMgr.h +++ b/src/world/Script/NativeScriptMgr.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "ScriptLoader.h" @@ -29,6 +30,8 @@ namespace Sapphire::Scripting */ std::queue< std::string > m_scriptLoadQueue; + std::recursive_mutex m_mutex; + /*! * @brief Used to unload a script * diff --git a/src/world/Script/ScriptLoader.cpp b/src/world/Script/ScriptLoader.cpp index 9e42af29..59d36ea6 100644 --- a/src/world/Script/ScriptLoader.cpp +++ b/src/world/Script/ScriptLoader.cpp @@ -74,6 +74,10 @@ Sapphire::Scripting::ScriptInfo* Sapphire::Scripting::ScriptLoader::loadModule( fs::create_directories( cacheDir ); fs::path dest( cacheDir /= f.filename().string() ); + // make sure the module has finished building before trying to copy it + if( fs::exists( f.string() + "_LOCK" ) ) + return nullptr; + try { fs::copy_file( f, dest, fs::copy_options::overwrite_existing );