Reformatted MTUtils with some refined directives.
Only whitespace changes in MTUtils.hpp !
This commit is contained in:
parent
121b6c078b
commit
75ed542686
@ -18,7 +18,7 @@ AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BraceWrapping:
|
||||
@ -37,18 +37,18 @@ BraceWrapping:
|
||||
SplitEmptyFunction: false
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: false
|
||||
BreakBeforeBinaryOperators: All
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeBraces: Custom
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: true
|
||||
ColumnLimit: 75
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
CompactNamespaces: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
|
@ -1,172 +1,218 @@
|
||||
#ifndef MTUTILS_HPP
|
||||
#define MTUTILS_HPP
|
||||
|
||||
#include <atomic> // for std::atomic_flag and memory orders
|
||||
#include <mutex> // for std::lock_guard
|
||||
#include <functional> // for std::function
|
||||
#include <utility> // for std::forward
|
||||
#include <atomic> // for std::atomic_flag and memory orders
|
||||
#include <mutex> // for std::lock_guard
|
||||
#include <functional> // for std::function
|
||||
#include <utility> // for std::forward
|
||||
#include <algorithm>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
/// Handy little spin mutex for the cached meshes.
|
||||
/// Implements the "Lockable" concept
|
||||
class SpinMutex {
|
||||
std::atomic_flag m_flg;
|
||||
class SpinMutex
|
||||
{
|
||||
std::atomic_flag m_flg;
|
||||
static const /*constexpr*/ auto MO_ACQ = std::memory_order_acquire;
|
||||
static const /*constexpr*/ auto MO_REL = std::memory_order_release;
|
||||
|
||||
public:
|
||||
inline SpinMutex() { m_flg.clear(MO_REL); }
|
||||
inline void lock() { while(m_flg.test_and_set(MO_ACQ)); }
|
||||
inline void lock() { while (m_flg.test_and_set(MO_ACQ)) ; }
|
||||
inline bool try_lock() { return !m_flg.test_and_set(MO_ACQ); }
|
||||
inline void unlock() { m_flg.clear(MO_REL); }
|
||||
};
|
||||
|
||||
/// A wrapper class around arbitrary object that needs thread safe caching.
|
||||
template<class T> class CachedObject {
|
||||
template<class T> class CachedObject
|
||||
{
|
||||
public:
|
||||
// Method type which refreshes the object when it has been invalidated
|
||||
using Setter = std::function<void(T&)>;
|
||||
using Setter = std::function<void(T &)>;
|
||||
|
||||
private:
|
||||
T m_obj; // the object itself
|
||||
bool m_valid; // invalidation flag
|
||||
SpinMutex m_lck; // to make the caching thread safe
|
||||
T m_obj; // the object itself
|
||||
bool m_valid; // invalidation flag
|
||||
SpinMutex m_lck; // to make the caching thread safe
|
||||
|
||||
// the setter will be called just before the object's const value is
|
||||
// about to be retrieved.
|
||||
std::function<void(T &)> m_setter;
|
||||
|
||||
// the setter will be called just before the object's const value is about
|
||||
// to be retrieved.
|
||||
std::function<void(T&)> m_setter;
|
||||
public:
|
||||
|
||||
// Forwarded constructor
|
||||
template<class...Args> inline CachedObject(Setter fn, Args&&...args):
|
||||
m_obj(std::forward<Args>(args)...), m_valid(false), m_setter(fn) {}
|
||||
template<class... Args>
|
||||
inline CachedObject(Setter fn, Args &&... args)
|
||||
: m_obj(std::forward<Args>(args)...), m_valid(false), m_setter(fn)
|
||||
{}
|
||||
|
||||
// invalidate the value of the object. The object will be refreshed at the
|
||||
// next retrieval (Setter will be called). The data that is used in
|
||||
// the setter function should be guarded as well during modification so the
|
||||
// modification has to take place in fn.
|
||||
inline void invalidate(std::function<void()> fn) {
|
||||
std::lock_guard<SpinMutex> lck(m_lck); fn(); m_valid = false;
|
||||
// invalidate the value of the object. The object will be refreshed at
|
||||
// the next retrieval (Setter will be called). The data that is used in
|
||||
// the setter function should be guarded as well during modification so
|
||||
// the modification has to take place in fn.
|
||||
inline void invalidate(std::function<void()> fn)
|
||||
{
|
||||
std::lock_guard<SpinMutex> lck(m_lck);
|
||||
fn();
|
||||
m_valid = false;
|
||||
}
|
||||
|
||||
// Get the const object properly updated.
|
||||
inline const T& get() {
|
||||
inline const T &get()
|
||||
{
|
||||
std::lock_guard<SpinMutex> lck(m_lck);
|
||||
if(!m_valid) { m_setter(m_obj); m_valid = true; }
|
||||
if (!m_valid) {
|
||||
m_setter(m_obj);
|
||||
m_valid = true;
|
||||
}
|
||||
return m_obj;
|
||||
}
|
||||
};
|
||||
|
||||
/// An std compatible random access iterator which uses indices to the source
|
||||
/// vector thus resistant to invalidation caused by relocations. It also "knows"
|
||||
/// its container. No comparison is neccesary to the container "end()" iterator.
|
||||
/// The template can be instantiated with a different value type than that of
|
||||
/// the container's but the types must be compatible. E.g. a base class of the
|
||||
/// contained objects is compatible.
|
||||
/// An std compatible random access iterator which uses indices to the
|
||||
/// source vector thus resistant to invalidation caused by relocations. It
|
||||
/// also "knows" its container. No comparison is neccesary to the container
|
||||
/// "end()" iterator. The template can be instantiated with a different
|
||||
/// value type than that of the container's but the types must be
|
||||
/// compatible. E.g. a base class of the contained objects is compatible.
|
||||
///
|
||||
/// For a constant iterator, one can instantiate this template with a value
|
||||
/// type preceded with 'const'.
|
||||
template<class Vector, // The container type, must be random access...
|
||||
template<class Vector, // The container type, must be random access...
|
||||
class Value = typename Vector::value_type // The value type
|
||||
>
|
||||
class IndexBasedIterator {
|
||||
class IndexBasedIterator
|
||||
{
|
||||
static const size_t NONE = size_t(-1);
|
||||
|
||||
std::reference_wrapper<Vector> m_index_ref;
|
||||
size_t m_idx = NONE;
|
||||
public:
|
||||
size_t m_idx = NONE;
|
||||
|
||||
using value_type = Value;
|
||||
using pointer = Value *;
|
||||
using reference = Value &;
|
||||
using difference_type = long;
|
||||
public:
|
||||
using value_type = Value;
|
||||
using pointer = Value *;
|
||||
using reference = Value &;
|
||||
using difference_type = long;
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
|
||||
inline explicit
|
||||
IndexBasedIterator(Vector& index, size_t idx):
|
||||
m_index_ref(index), m_idx(idx) {}
|
||||
inline explicit IndexBasedIterator(Vector &index, size_t idx)
|
||||
: m_index_ref(index), m_idx(idx)
|
||||
{}
|
||||
|
||||
// Post increment
|
||||
inline IndexBasedIterator operator++(int) {
|
||||
IndexBasedIterator cpy(*this); ++m_idx; return cpy;
|
||||
inline IndexBasedIterator operator++(int)
|
||||
{
|
||||
IndexBasedIterator cpy(*this);
|
||||
++m_idx;
|
||||
return cpy;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator operator--(int) {
|
||||
IndexBasedIterator cpy(*this); --m_idx; return cpy;
|
||||
inline IndexBasedIterator operator--(int)
|
||||
{
|
||||
IndexBasedIterator cpy(*this);
|
||||
--m_idx;
|
||||
return cpy;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator++() {
|
||||
++m_idx; return *this;
|
||||
inline IndexBasedIterator &operator++()
|
||||
{
|
||||
++m_idx;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator--() {
|
||||
--m_idx; return *this;
|
||||
inline IndexBasedIterator &operator--()
|
||||
{
|
||||
--m_idx;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator+=(difference_type l) {
|
||||
m_idx += size_t(l); return *this;
|
||||
inline IndexBasedIterator &operator+=(difference_type l)
|
||||
{
|
||||
m_idx += size_t(l);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator operator+(difference_type l) {
|
||||
auto cpy = *this; cpy += l; return cpy;
|
||||
inline IndexBasedIterator operator+(difference_type l)
|
||||
{
|
||||
auto cpy = *this;
|
||||
cpy += l;
|
||||
return cpy;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator& operator-=(difference_type l) {
|
||||
m_idx -= size_t(l); return *this;
|
||||
inline IndexBasedIterator &operator-=(difference_type l)
|
||||
{
|
||||
m_idx -= size_t(l);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline IndexBasedIterator operator-(difference_type l) {
|
||||
auto cpy = *this; cpy -= l; return cpy;
|
||||
inline IndexBasedIterator operator-(difference_type l)
|
||||
{
|
||||
auto cpy = *this;
|
||||
cpy -= l;
|
||||
return cpy;
|
||||
}
|
||||
|
||||
operator difference_type() { return difference_type(m_idx); }
|
||||
|
||||
/// Tesing the end of the container... this is not possible with std
|
||||
/// iterators.
|
||||
inline bool is_end() const { return m_idx >= m_index_ref.get().size();}
|
||||
inline bool is_end() const
|
||||
{
|
||||
return m_idx >= m_index_ref.get().size();
|
||||
}
|
||||
|
||||
inline Value & operator*() const {
|
||||
inline Value &operator*() const
|
||||
{
|
||||
assert(m_idx < m_index_ref.get().size());
|
||||
return m_index_ref.get().operator[](m_idx);
|
||||
}
|
||||
|
||||
inline Value * operator->() const {
|
||||
inline Value *operator->() const
|
||||
{
|
||||
assert(m_idx < m_index_ref.get().size());
|
||||
return &m_index_ref.get().operator[](m_idx);
|
||||
}
|
||||
|
||||
/// If both iterators point past the container, they are equal...
|
||||
inline bool operator ==(const IndexBasedIterator& other) {
|
||||
inline bool operator==(const IndexBasedIterator &other)
|
||||
{
|
||||
size_t e = m_index_ref.get().size();
|
||||
return m_idx == other.m_idx || (m_idx >= e && other.m_idx >= e);
|
||||
}
|
||||
|
||||
inline bool operator !=(const IndexBasedIterator& other) {
|
||||
inline bool operator!=(const IndexBasedIterator &other)
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
inline bool operator <=(const IndexBasedIterator& other) {
|
||||
inline bool operator<=(const IndexBasedIterator &other)
|
||||
{
|
||||
return (m_idx < other.m_idx) || (*this == other);
|
||||
}
|
||||
|
||||
inline bool operator <(const IndexBasedIterator& other) {
|
||||
inline bool operator<(const IndexBasedIterator &other)
|
||||
{
|
||||
return m_idx < other.m_idx && (*this != other);
|
||||
}
|
||||
|
||||
inline bool operator >=(const IndexBasedIterator& other) {
|
||||
inline bool operator>=(const IndexBasedIterator &other)
|
||||
{
|
||||
return m_idx > other.m_idx || *this == other;
|
||||
}
|
||||
|
||||
inline bool operator >(const IndexBasedIterator& other) {
|
||||
inline bool operator>(const IndexBasedIterator &other)
|
||||
{
|
||||
return m_idx > other.m_idx && *this != other;
|
||||
}
|
||||
};
|
||||
|
||||
/// A very simple range concept implementation with iterator-like objects.
|
||||
template<class It> class Range {
|
||||
template<class It> class Range
|
||||
{
|
||||
It from, to;
|
||||
public:
|
||||
|
||||
public:
|
||||
// The class is ready for range based for loops.
|
||||
It begin() const { return from; }
|
||||
It end() const { return to; }
|
||||
@ -175,15 +221,17 @@ public:
|
||||
using Type = It;
|
||||
|
||||
Range() = default;
|
||||
Range(It &&b, It &&e):
|
||||
from(std::forward<It>(b)), to(std::forward<It>(e)) {}
|
||||
Range(It &&b, It &&e)
|
||||
: from(std::forward<It>(b)), to(std::forward<It>(e))
|
||||
{}
|
||||
|
||||
// Some useful container-like methods...
|
||||
inline size_t size() const { return end() - begin(); }
|
||||
inline bool empty() const { return size() == 0; }
|
||||
inline bool empty() const { return size() == 0; }
|
||||
};
|
||||
|
||||
template<class C> bool all_of(const C &container) {
|
||||
template<class C> bool all_of(const C &container)
|
||||
{
|
||||
return std::all_of(container.begin(),
|
||||
container.end(),
|
||||
[](const typename C::value_type &v) {
|
||||
@ -200,6 +248,6 @@ template<class X, class Y> inline X ceil_i(X x, Y y)
|
||||
return (x % y) ? x / y + 1 : x / y;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // MTUTILS_HPP
|
||||
|
Loading…
Reference in New Issue
Block a user