mirror of https://github.com/AxioDL/metaforce.git
Add ResourceLock for detecting parallel resource collisions
This commit is contained in:
parent
48a4a51853
commit
719c62f09f
|
@ -9,6 +9,7 @@
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
#include <hecl/hecl.hpp>
|
#include <hecl/hecl.hpp>
|
||||||
#include <hecl/Database.hpp>
|
#include <hecl/Database.hpp>
|
||||||
|
|
|
@ -68,6 +68,7 @@ private:
|
||||||
size_t _writeBuf(const void* buf, size_t len);
|
size_t _writeBuf(const void* buf, size_t len);
|
||||||
void _closePipe();
|
void _closePipe();
|
||||||
void _blenderDied();
|
void _blenderDied();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BlenderConnection(int verbosityLevel=1);
|
BlenderConnection(int verbosityLevel=1);
|
||||||
~BlenderConnection();
|
~BlenderConnection();
|
||||||
|
|
|
@ -370,6 +370,7 @@ try:
|
||||||
|
|
||||||
elif cmdargs[0] == 'SAVE':
|
elif cmdargs[0] == 'SAVE':
|
||||||
bpy.context.user_preferences.filepaths.save_version = 0
|
bpy.context.user_preferences.filepaths.save_version = 0
|
||||||
|
print('SAVING %s' % loaded_blend)
|
||||||
if loaded_blend:
|
if loaded_blend:
|
||||||
if 'FINISHED' in bpy.ops.wm.save_as_mainfile(filepath=loaded_blend, check_existing=False, compress=True):
|
if 'FINISHED' in bpy.ops.wm.save_as_mainfile(filepath=loaded_blend, check_existing=False, compress=True):
|
||||||
writepipeline(b'FINISHED')
|
writepipeline(b'FINISHED')
|
||||||
|
|
|
@ -44,7 +44,6 @@ class Project;
|
||||||
struct DataSpecEntry;
|
struct DataSpecEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
extern unsigned VerbosityLevel;
|
extern unsigned VerbosityLevel;
|
||||||
extern logvisor::Module LogModule;
|
extern logvisor::Module LogModule;
|
||||||
|
|
||||||
|
@ -1180,6 +1179,28 @@ public:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mutex-style centralized resource-path tracking
|
||||||
|
*
|
||||||
|
* Provides a means to safely parallelize resource processing; detecting when another
|
||||||
|
* thread is working on the same resource.
|
||||||
|
*/
|
||||||
|
class ResourceLock
|
||||||
|
{
|
||||||
|
static bool SetThreadRes(const ProjectPath& path);
|
||||||
|
static void ClearThreadRes();
|
||||||
|
bool good;
|
||||||
|
public:
|
||||||
|
operator bool() const { return good; }
|
||||||
|
static bool InProgress(const ProjectPath& path);
|
||||||
|
ResourceLock(const ProjectPath& path) { good = SetThreadRes(path); }
|
||||||
|
~ResourceLock() { if (good) ClearThreadRes(); }
|
||||||
|
ResourceLock(const ResourceLock&) = delete;
|
||||||
|
ResourceLock& operator=(const ResourceLock&) = delete;
|
||||||
|
ResourceLock(ResourceLock&&) = delete;
|
||||||
|
ResourceLock& operator=(ResourceLock&&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Search from within provided directory for the project root
|
* @brief Search from within provided directory for the project root
|
||||||
* @param path absolute or relative file path to search from
|
* @param path absolute or relative file path to search from
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
#include "hecl/hecl.hpp"
|
#include "hecl/hecl.hpp"
|
||||||
|
#include <thread>
|
||||||
|
#include <mutex>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
@ -84,6 +87,38 @@ void SanitizePath(std::wstring& path)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::mutex PathsMutex;
|
||||||
|
static std::unordered_map<std::thread::id, ProjectPath> PathsInProgress;
|
||||||
|
|
||||||
|
bool ResourceLock::InProgress(const ProjectPath& path)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(PathsMutex);
|
||||||
|
for (const auto& p : PathsInProgress)
|
||||||
|
if (p.second == path)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResourceLock::SetThreadRes(const ProjectPath& path)
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(PathsMutex);
|
||||||
|
if (PathsInProgress.find(std::this_thread::get_id()) != PathsInProgress.cend())
|
||||||
|
LogModule.report(logvisor::Fatal, "multiple resource locks on thread");
|
||||||
|
|
||||||
|
for (const auto& p : PathsInProgress)
|
||||||
|
if (p.second == path)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
PathsInProgress[std::this_thread::get_id()] = path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResourceLock::ClearThreadRes()
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> lk(PathsMutex);
|
||||||
|
PathsInProgress.erase(std::this_thread::get_id());
|
||||||
|
}
|
||||||
|
|
||||||
bool IsPathPNG(const hecl::ProjectPath& path)
|
bool IsPathPNG(const hecl::ProjectPath& path)
|
||||||
{
|
{
|
||||||
FILE* fp = hecl::Fopen(path.getAbsolutePath().c_str(), _S("rb"));
|
FILE* fp = hecl::Fopen(path.getAbsolutePath().c_str(), _S("rb"));
|
||||||
|
|
Loading…
Reference in New Issue