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 <chrono>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include <hecl/hecl.hpp>
|
||||
#include <hecl/Database.hpp>
|
||||
|
|
|
@ -68,6 +68,7 @@ private:
|
|||
size_t _writeBuf(const void* buf, size_t len);
|
||||
void _closePipe();
|
||||
void _blenderDied();
|
||||
|
||||
public:
|
||||
BlenderConnection(int verbosityLevel=1);
|
||||
~BlenderConnection();
|
||||
|
|
|
@ -370,6 +370,7 @@ try:
|
|||
|
||||
elif cmdargs[0] == 'SAVE':
|
||||
bpy.context.user_preferences.filepaths.save_version = 0
|
||||
print('SAVING %s' % loaded_blend)
|
||||
if loaded_blend:
|
||||
if 'FINISHED' in bpy.ops.wm.save_as_mainfile(filepath=loaded_blend, check_existing=False, compress=True):
|
||||
writepipeline(b'FINISHED')
|
||||
|
|
|
@ -44,7 +44,6 @@ class Project;
|
|||
struct DataSpecEntry;
|
||||
}
|
||||
|
||||
|
||||
extern unsigned VerbosityLevel;
|
||||
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
|
||||
* @param path absolute or relative file path to search from
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
#include "hecl/hecl.hpp"
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#ifdef WIN32
|
||||
#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)
|
||||
{
|
||||
FILE* fp = hecl::Fopen(path.getAbsolutePath().c_str(), _S("rb"));
|
||||
|
|
Loading…
Reference in New Issue