OrcaSlicer latest
OrcaSlicer
Loading...
Searching...
No Matches
Slic3r::InstanceLock Class Reference

#include </home/runner/work/OrcaSlicer/OrcaSlicer/src/libslic3r/InstanceLock.hpp>

Collaboration diagram for Slic3r::InstanceLock:

Classes

struct  Slot

Public Member Functions

 InstanceLock (const std::string &lock_file_path, std::chrono::milliseconds timeout=default_timeout)
 ~InstanceLock ()
 InstanceLock (const InstanceLock &)=delete
InstanceLock & operator= (const InstanceLock &)=delete
bool locked () const

Static Public Attributes

static constexpr std::chrono::milliseconds default_timeout {1000}
static std::chrono::milliseconds cooldown {10000}

Static Private Member Functions

static Slot & slot_for (const std::string &lock_file_path)
static bool open_lock_file (Slot &slot, const std::string &lock_file_path)
static void defer (Slot &slot, const std::string &reason)

Private Attributes

Slot * m_slot {nullptr}
std::unique_lock< std::recursive_mutex > m_slot_guard
bool m_locked {false}

Detailed Description


Class Documentation

◆ Slic3r::InstanceLock::Slot

struct Slic3r::InstanceLock::Slot
Collaboration diagram for Slic3r::InstanceLock::Slot:
Class Members
time_point cooldown_until {}
int depth {0}
unique_ptr< NativeFileLock > file_lock
recursive_mutex mutex

Constructor & Destructor Documentation

◆ InstanceLock() [1/2]

Slic3r::InstanceLock::InstanceLock ( const std::string & lock_file_path,
std::chrono::milliseconds timeout = default_timeout )
explicit
125{
126 if (lock_file_path.empty())
127 return;
128 m_slot = &slot_for(lock_file_path);
129 m_slot_guard = std::unique_lock<std::recursive_mutex>(m_slot->mutex);
130 const auto now = std::chrono::steady_clock::now();
131 if (m_slot->depth == 0 && now >= m_slot->cooldown_until && open_lock_file(*m_slot, lock_file_path)) {
132 const auto deadline = now + timeout;
133 bool taken = false;
134 for (;;) {
135 try {
136 if ((taken = m_slot->file_lock->try_lock()))
137 break;
138 } catch (const std::exception &e) {
139 defer(*m_slot, "Cannot lock " + lock_file_path + ": " + e.what());
140 break;
141 }
142 if (std::chrono::steady_clock::now() >= deadline) {
143 defer(*m_slot, "Another instance has held " + lock_file_path + " for over " + std::to_string(timeout.count()) + " ms");
144 break;
145 }
146 std::this_thread::sleep_for(std::chrono::milliseconds(5));
147 }
148 if (! taken)
149 m_slot->file_lock.reset();
150 }
151 // Counted last, so a throw above leaves the slot exactly as it was found.
152 ++ m_slot->depth;
153 m_locked = m_slot->file_lock != nullptr;
154}
static void defer(Slot &slot, const std::string &reason)
Definition InstanceLock.cpp:94
bool m_locked
Definition InstanceLock.hpp:57
Slot * m_slot
Definition InstanceLock.hpp:55
std::unique_lock< std::recursive_mutex > m_slot_guard
Definition InstanceLock.hpp:56
static Slot & slot_for(const std::string &lock_file_path)
Definition InstanceLock.cpp:80
static bool open_lock_file(Slot &slot, const std::string &lock_file_path)
Definition InstanceLock.cpp:102

References defer(), m_locked, m_slot, m_slot_guard, open_lock_file(), and slot_for().

Referenced by InstanceLock(), and operator=().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ~InstanceLock()

Slic3r::InstanceLock::~InstanceLock ( )
157{
158 if (m_slot == nullptr)
159 return;
160 if (-- m_slot->depth == 0 && m_slot->file_lock) {
161 try {
162 m_slot->file_lock->unlock();
163 } catch (const std::exception &e) {
164 BOOST_LOG_TRIVIAL(warning) << "Cannot unlock instance lock: " << e.what();
165 }
166 m_slot->file_lock.reset();
167 }
168}

References m_slot.

◆ InstanceLock() [2/2]

Slic3r::InstanceLock::InstanceLock ( const InstanceLock & )
delete

References InstanceLock().

Here is the call graph for this function:

Member Function Documentation

◆ defer()

void Slic3r::InstanceLock::defer ( Slot & slot,
const std::string & reason )
staticprivate
95{
96 slot.cooldown_until = std::chrono::steady_clock::now() + cooldown;
97 BOOST_LOG_TRIVIAL(warning) << reason << "; proceeding without the lock for the next " << cooldown.count() << " ms";
98}
static std::chrono::milliseconds cooldown
Definition InstanceLock.hpp:37

References cooldown, and Slic3r::InstanceLock::Slot::cooldown_until.

Referenced by InstanceLock(), and open_lock_file().

Here is the caller graph for this function:

◆ locked()

bool Slic3r::InstanceLock::locked ( ) const
inline
47{ return m_locked; }

References m_locked.

Referenced by Slic3r::PresetBundle::migrate_legacy_user_filament_presets().

Here is the caller graph for this function:

◆ open_lock_file()

bool Slic3r::InstanceLock::open_lock_file ( Slot & slot,
const std::string & lock_file_path )
staticprivate
103{
104 try {
105#ifdef _WIN32
106 // The lock opens an existing file; created once, on the first miss.
107 const std::wstring wide_path = boost::nowide::widen(lock_file_path);
108 try {
109 slot.file_lock = std::make_unique<NativeFileLock>(wide_path.c_str());
110 } catch (const std::exception &) {
111 boost::nowide::ofstream(lock_file_path, std::ios::app).close();
112 slot.file_lock = std::make_unique<NativeFileLock>(wide_path.c_str());
113 }
114#else
115 slot.file_lock = std::make_unique<NativeFileLock>(lock_file_path.c_str());
116#endif
117 return true;
118 } catch (const std::exception &e) {
119 defer(slot, "Cannot open lock file " + lock_file_path + ": " + e.what() + " (check its owner and permissions)");
120 return false;
121 }
122}

References defer(), and Slic3r::InstanceLock::Slot::file_lock.

Referenced by InstanceLock().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ operator=()

InstanceLock & Slic3r::InstanceLock::operator= ( const InstanceLock & )
delete

References InstanceLock().

Here is the call graph for this function:

◆ slot_for()

InstanceLock::Slot & Slic3r::InstanceLock::slot_for ( const std::string & lock_file_path)
staticprivate
81{
82 // Never freed: a save during static destruction still needs its slot.
83 static auto *registry_mutex = new std::mutex();
84 static auto *registry = new std::map<std::string, std::unique_ptr<Slot>>();
85
86 std::lock_guard<std::mutex> guard(*registry_mutex);
87 std::unique_ptr<Slot> &slot = (*registry)[lock_file_path];
88 if (! slot)
89 slot = std::make_unique<Slot>();
90 return *slot;
91}

Referenced by InstanceLock().

Here is the caller graph for this function:

Member Data Documentation

◆ cooldown

std::chrono::milliseconds Slic3r::InstanceLock::cooldown {10000}
inlinestatic
37{10000};

Referenced by defer().

◆ default_timeout

std::chrono::milliseconds Slic3r::InstanceLock::default_timeout {1000}
staticconstexpr
34{1000};

◆ m_locked

bool Slic3r::InstanceLock::m_locked {false}
private
57{false};

Referenced by InstanceLock(), and locked().

◆ m_slot

Slot* Slic3r::InstanceLock::m_slot {nullptr}
private
55{nullptr};

Referenced by InstanceLock(), and ~InstanceLock().

◆ m_slot_guard

std::unique_lock<std::recursive_mutex> Slic3r::InstanceLock::m_slot_guard
private

Referenced by InstanceLock().


The documentation for this class was generated from the following files: