Reformatted MTUtils with some refined directives.

Only whitespace changes in MTUtils.hpp !
This commit is contained in:
tamasmeszaros 2019-06-24 13:03:46 +02:00
parent 121b6c078b
commit 75ed542686
2 changed files with 128 additions and 80 deletions

View File

@ -18,7 +18,7 @@ AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes AlwaysBreakTemplateDeclarations: false
BinPackArguments: false BinPackArguments: false
BinPackParameters: false BinPackParameters: false
BraceWrapping: BraceWrapping:
@ -37,18 +37,18 @@ BraceWrapping:
SplitEmptyFunction: false SplitEmptyFunction: false
SplitEmptyRecord: false SplitEmptyRecord: false
SplitEmptyNamespace: false SplitEmptyNamespace: false
BreakBeforeBinaryOperators: All BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true BreakBeforeTernaryOperators: false
BreakConstructorInitializersBeforeComma: false BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: false BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true BreakStringLiterals: true
ColumnLimit: 75 ColumnLimit: 75
CommentPragmas: '^ IWYU pragma:' CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false CompactNamespaces: true
ConstructorInitializerAllOnOneLineOrOnePerLine: true ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4 ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4 ContinuationIndentWidth: 4

View File

@ -1,172 +1,218 @@
#ifndef MTUTILS_HPP #ifndef MTUTILS_HPP
#define MTUTILS_HPP #define MTUTILS_HPP
#include <atomic> // for std::atomic_flag and memory orders #include <atomic> // for std::atomic_flag and memory orders
#include <mutex> // for std::lock_guard #include <mutex> // for std::lock_guard
#include <functional> // for std::function #include <functional> // for std::function
#include <utility> // for std::forward #include <utility> // for std::forward
#include <algorithm> #include <algorithm>
namespace Slic3r { namespace Slic3r {
/// Handy little spin mutex for the cached meshes. /// Handy little spin mutex for the cached meshes.
/// Implements the "Lockable" concept /// Implements the "Lockable" concept
class SpinMutex { class SpinMutex
std::atomic_flag m_flg; {
std::atomic_flag m_flg;
static const /*constexpr*/ auto MO_ACQ = std::memory_order_acquire; static const /*constexpr*/ auto MO_ACQ = std::memory_order_acquire;
static const /*constexpr*/ auto MO_REL = std::memory_order_release; static const /*constexpr*/ auto MO_REL = std::memory_order_release;
public: public:
inline SpinMutex() { m_flg.clear(MO_REL); } 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 bool try_lock() { return !m_flg.test_and_set(MO_ACQ); }
inline void unlock() { m_flg.clear(MO_REL); } inline void unlock() { m_flg.clear(MO_REL); }
}; };
/// A wrapper class around arbitrary object that needs thread safe caching. /// A wrapper class around arbitrary object that needs thread safe caching.
template<class T> class CachedObject { template<class T> class CachedObject
{
public: public:
// Method type which refreshes the object when it has been invalidated // Method type which refreshes the object when it has been invalidated
using Setter = std::function<void(T&)>; using Setter = std::function<void(T &)>;
private: private:
T m_obj; // the object itself T m_obj; // the object itself
bool m_valid; // invalidation flag bool m_valid; // invalidation flag
SpinMutex m_lck; // to make the caching thread safe 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: public:
// Forwarded constructor // Forwarded constructor
template<class...Args> inline CachedObject(Setter fn, Args&&...args): template<class... Args>
m_obj(std::forward<Args>(args)...), m_valid(false), m_setter(fn) {} 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 // invalidate the value of the object. The object will be refreshed at
// next retrieval (Setter will be called). The data that is used in // 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 // the setter function should be guarded as well during modification so
// modification has to take place in fn. // the modification has to take place in fn.
inline void invalidate(std::function<void()> fn) { inline void invalidate(std::function<void()> fn)
std::lock_guard<SpinMutex> lck(m_lck); fn(); m_valid = false; {
std::lock_guard<SpinMutex> lck(m_lck);
fn();
m_valid = false;
} }
// Get the const object properly updated. // Get the const object properly updated.
inline const T& get() { inline const T &get()
{
std::lock_guard<SpinMutex> lck(m_lck); 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; return m_obj;
} }
}; };
/// An std compatible random access iterator which uses indices to the source /// An std compatible random access iterator which uses indices to the
/// vector thus resistant to invalidation caused by relocations. It also "knows" /// source vector thus resistant to invalidation caused by relocations. It
/// its container. No comparison is neccesary to the container "end()" iterator. /// also "knows" its container. No comparison is neccesary to the container
/// The template can be instantiated with a different value type than that of /// "end()" iterator. The template can be instantiated with a different
/// the container's but the types must be compatible. E.g. a base class of the /// value type than that of the container's but the types must be
/// contained objects is compatible. /// compatible. E.g. a base class of the contained objects is compatible.
/// ///
/// For a constant iterator, one can instantiate this template with a value /// For a constant iterator, one can instantiate this template with a value
/// type preceded with 'const'. /// 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 Value = typename Vector::value_type // The value type
> >
class IndexBasedIterator { class IndexBasedIterator
{
static const size_t NONE = size_t(-1); static const size_t NONE = size_t(-1);
std::reference_wrapper<Vector> m_index_ref; std::reference_wrapper<Vector> m_index_ref;
size_t m_idx = NONE; size_t m_idx = NONE;
public:
using value_type = Value; public:
using pointer = Value *; using value_type = Value;
using reference = Value &; using pointer = Value *;
using difference_type = long; using reference = Value &;
using difference_type = long;
using iterator_category = std::random_access_iterator_tag; using iterator_category = std::random_access_iterator_tag;
inline explicit inline explicit IndexBasedIterator(Vector &index, size_t idx)
IndexBasedIterator(Vector& index, size_t idx): : m_index_ref(index), m_idx(idx)
m_index_ref(index), m_idx(idx) {} {}
// Post increment // Post increment
inline IndexBasedIterator operator++(int) { inline IndexBasedIterator operator++(int)
IndexBasedIterator cpy(*this); ++m_idx; return cpy; {
IndexBasedIterator cpy(*this);
++m_idx;
return cpy;
} }
inline IndexBasedIterator operator--(int) { inline IndexBasedIterator operator--(int)
IndexBasedIterator cpy(*this); --m_idx; return cpy; {
IndexBasedIterator cpy(*this);
--m_idx;
return cpy;
} }
inline IndexBasedIterator& operator++() { inline IndexBasedIterator &operator++()
++m_idx; return *this; {
++m_idx;
return *this;
} }
inline IndexBasedIterator& operator--() { inline IndexBasedIterator &operator--()
--m_idx; return *this; {
--m_idx;
return *this;
} }
inline IndexBasedIterator& operator+=(difference_type l) { inline IndexBasedIterator &operator+=(difference_type l)
m_idx += size_t(l); return *this; {
m_idx += size_t(l);
return *this;
} }
inline IndexBasedIterator operator+(difference_type l) { inline IndexBasedIterator operator+(difference_type l)
auto cpy = *this; cpy += l; return cpy; {
auto cpy = *this;
cpy += l;
return cpy;
} }
inline IndexBasedIterator& operator-=(difference_type l) { inline IndexBasedIterator &operator-=(difference_type l)
m_idx -= size_t(l); return *this; {
m_idx -= size_t(l);
return *this;
} }
inline IndexBasedIterator operator-(difference_type l) { inline IndexBasedIterator operator-(difference_type l)
auto cpy = *this; cpy -= l; return cpy; {
auto cpy = *this;
cpy -= l;
return cpy;
} }
operator difference_type() { return difference_type(m_idx); } operator difference_type() { return difference_type(m_idx); }
/// Tesing the end of the container... this is not possible with std /// Tesing the end of the container... this is not possible with std
/// iterators. /// 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()); assert(m_idx < m_index_ref.get().size());
return m_index_ref.get().operator[](m_idx); return m_index_ref.get().operator[](m_idx);
} }
inline Value * operator->() const { inline Value *operator->() const
{
assert(m_idx < m_index_ref.get().size()); assert(m_idx < m_index_ref.get().size());
return &m_index_ref.get().operator[](m_idx); return &m_index_ref.get().operator[](m_idx);
} }
/// If both iterators point past the container, they are equal... /// 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(); size_t e = m_index_ref.get().size();
return m_idx == other.m_idx || (m_idx >= e && other.m_idx >= e); 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); return !(*this == other);
} }
inline bool operator <=(const IndexBasedIterator& other) { inline bool operator<=(const IndexBasedIterator &other)
{
return (m_idx < other.m_idx) || (*this == 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); 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; 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; return m_idx > other.m_idx && *this != other;
} }
}; };
/// A very simple range concept implementation with iterator-like objects. /// A very simple range concept implementation with iterator-like objects.
template<class It> class Range { template<class It> class Range
{
It from, to; It from, to;
public:
public:
// The class is ready for range based for loops. // The class is ready for range based for loops.
It begin() const { return from; } It begin() const { return from; }
It end() const { return to; } It end() const { return to; }
@ -175,15 +221,17 @@ public:
using Type = It; using Type = It;
Range() = default; Range() = default;
Range(It &&b, It &&e): Range(It &&b, It &&e)
from(std::forward<It>(b)), to(std::forward<It>(e)) {} : from(std::forward<It>(b)), to(std::forward<It>(e))
{}
// Some useful container-like methods... // Some useful container-like methods...
inline size_t size() const { return end() - begin(); } 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(), return std::all_of(container.begin(),
container.end(), container.end(),
[](const typename C::value_type &v) { [](const typename C::value_type &v) {
@ -196,10 +244,10 @@ template<class X, class Y> inline X ceil_i(X x, Y y)
static_assert(std::is_integral<X>::value && static_assert(std::is_integral<X>::value &&
std::is_integral<Y>::value && sizeof(X) >= sizeof(Y), std::is_integral<Y>::value && sizeof(X) >= sizeof(Y),
""); "");
return (x % y) ? x / y + 1 : x / y; return (x % y) ? x / y + 1 : x / y;
} }
} } // namespace Slic3r
#endif // MTUTILS_HPP #endif // MTUTILS_HPP