diff --git a/build.sh b/build.sh
index 1413134cc..ae7aa09bd 100755
--- a/build.sh
+++ b/build.sh
@@ -41,6 +41,7 @@ HAVE_CURL=0
HAVE_EXPAT=0
HAVE_GIT2=1
HAVE_LSTREAM=1
+HAVE_CPP20=0
RUBYINCLUDE=""
RUBYINCLUDE2=""
@@ -217,6 +218,9 @@ while [ "$*" != "" ]; do
-nolstream)
HAVE_LSTREAM=0
;;
+ -cpp20)
+ HAVE_CPP20=1
+ ;;
-qt5)
echo "*** WARNING: -qt5 option is ignored - Qt version is auto-detected now."
;;
@@ -275,6 +279,7 @@ while [ "$*" != "" ]; do
echo " -libpng Use libpng instead of Qt for PNG generation"
echo " -nolibgit2 Do not include libgit2 for Git package support"
echo " -nolstream Do not include the LStream plugin"
+ echo " -cpp20 Uses some C++20 features (e.g. atomics)"
echo ""
echo "Environment Variables:"
echo ""
@@ -670,6 +675,7 @@ qmake_options=(
HAVE_PNG="$HAVE_PNG"
HAVE_GIT2="$HAVE_GIT2"
HAVE_LSTREAM="$HAVE_LSTREAM"
+ HAVE_CPP20="$HAVE_CPP20"
PREFIX="$BIN"
RPATH="$RPATH"
KLAYOUT_VERSION="$KLAYOUT_VERSION"
diff --git a/src/klayout.pri b/src/klayout.pri
index 067942aec..c21ae29d8 100644
--- a/src/klayout.pri
+++ b/src/klayout.pri
@@ -204,12 +204,16 @@ msvc {
# -Wno-reserved-user-defined-literal \
#
- lessThan(QT_MAJOR_VERSION, 6) {
- # because we use unordered_map/unordered_set:
- QMAKE_CXXFLAGS += -std=c++11
+ equals(HAVE_CPP20, "1") {
+ QMAKE_CXXFLAGS += -std=c++20
+ DEFINES += HAVE_CPP20
} else {
- # because we use unordered_map/unordered_set:
- QMAKE_CXXFLAGS += -std=c++17
+ lessThan(QT_MAJOR_VERSION, 6) {
+ # because we use unordered_map/unordered_set:
+ QMAKE_CXXFLAGS += -std=c++11
+ } else {
+ QMAKE_CXXFLAGS += -std=c++17
+ }
}
win32 {
diff --git a/src/tl/tl/atomic/atomic.h b/src/tl/tl/atomic/atomic.h
deleted file mode 100644
index 45f2af681..000000000
--- a/src/tl/tl/atomic/atomic.h
+++ /dev/null
@@ -1,203 +0,0 @@
-//----------------------------------------------------------------------------
-// This is free and unencumbered software released into the public domain.
-//
-// Anyone is free to copy, modify, publish, use, compile, sell, or distribute
-// this software, either in source code form or as a compiled binary, for any
-// purpose, commercial or non-commercial, and by any means.
-//
-// In jurisdictions that recognize copyright laws, the author or authors of
-// this software dedicate any and all copyright interest in the software to the
-// public domain. We make this dedication for the benefit of the public at
-// large and to the detriment of our heirs and successors. We intend this
-// dedication to be an overt act of relinquishment in perpetuity of all present
-// and future rights to this software under copyright law.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-// For more information, please refer to
-//-----------------------------------------------------------------------------
-
-#ifndef ATOMIC_ATOMIC_H_
-#define ATOMIC_ATOMIC_H_
-
-// Macro for disallowing copying of an object.
-#if __cplusplus >= 201103L
-#define ATOMIC_DISALLOW_COPY(T) \
- T(const T&) = delete; \
- T& operator=(const T&) = delete;
-#else
-#define ATOMIC_DISALLOW_COPY(T) \
- T(const T&); \
- T& operator=(const T&);
-#endif
-
-// A portable static assert.
-#if __cplusplus >= 201103L
-#define ATOMIC_STATIC_ASSERT(condition, message) \
- static_assert((condition), message)
-#else
-// Based on: http://stackoverflow.com/a/809465/5778708
-#define ATOMIC_STATIC_ASSERT(condition, message) \
- _impl_STATIC_ASSERT_LINE(condition, __LINE__)
-#define _impl_PASTE(a, b) a##b
-#ifdef __GNUC__
-#define _impl_UNUSED __attribute__((__unused__))
-#else
-#define _impl_UNUSED
-#endif
-#define _impl_STATIC_ASSERT_LINE(condition, line) \
- typedef char _impl_PASTE( \
- STATIC_ASSERT_failed_, \
- line)[(2 * static_cast(!!(condition))) - 1] _impl_UNUSED
-#endif
-
-#if defined(__GNUC__) || defined(__clang__) || defined(__xlc__)
-#define ATOMIC_USE_GCC_INTRINSICS
-#elif defined(_MSC_VER)
-#define ATOMIC_USE_MSVC_INTRINSICS
-#include "atomic_msvc.h"
-#elif __cplusplus >= 201103L
-#define ATOMIC_USE_CPP11_ATOMIC
-#include
-#else
-#error Unsupported compiler / system.
-#endif
-
-namespace atomic {
-template
-class atomic {
-public:
- ATOMIC_STATIC_ASSERT(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 ||
- sizeof(T) == 8,
- "Only types of size 1, 2, 4 or 8 are supported");
-
- atomic() : value_(static_cast(0)) {}
-
- explicit atomic(const T value) : value_(value) {}
-
- /// @brief Performs an atomic increment operation (value + 1).
- /// @returns The new value of the atomic object.
- T operator++() {
-#if defined(ATOMIC_USE_GCC_INTRINSICS)
- return __atomic_add_fetch(&value_, 1, __ATOMIC_SEQ_CST);
-#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
- return msvc::interlocked::increment(&value_);
-#else
- return ++value_;
-#endif
- }
-
- /// @brief Performs an atomic decrement operation (value - 1).
- /// @returns The new value of the atomic object.
- T operator--() {
-#if defined(ATOMIC_USE_GCC_INTRINSICS)
- return __atomic_sub_fetch(&value_, 1, __ATOMIC_SEQ_CST);
-#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
- return msvc::interlocked::decrement(&value_);
-#else
- return --value_;
-#endif
- }
-
- /// @brief Performs an atomic compare-and-swap (CAS) operation.
- ///
- /// The value of the atomic object is only updated to the new value if the
- /// old value of the atomic object matches @c expected_val.
- ///
- /// @param expected_val The expected value of the atomic object.
- /// @param new_val The new value to write to the atomic object.
- /// @returns True if new_value was written to the atomic object.
- bool compare_exchange(const T expected_val, const T new_val) {
-#if defined(ATOMIC_USE_GCC_INTRINSICS)
- T e = expected_val;
- return __atomic_compare_exchange_n(
- &value_, &e, new_val, true, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
-#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
- const T old_val =
- msvc::interlocked::compare_exchange(&value_, new_val, expected_val);
- return (old_val == expected_val);
-#else
- T e = expected_val;
- return value_.compare_exchange_weak(e, new_val);
-#endif
- }
-
- /// @brief Performs an atomic set operation.
- ///
- /// The value of the atomic object is unconditionally updated to the new
- /// value.
- ///
- /// @param new_val The new value to write to the atomic object.
- void store(const T new_val) {
-#if defined(ATOMIC_USE_GCC_INTRINSICS)
- __atomic_store_n(&value_, new_val, __ATOMIC_SEQ_CST);
-#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
- (void)msvc::interlocked::exchange(&value_, new_val);
-#else
- value_.store(new_val);
-#endif
- }
-
- /// @returns the current value of the atomic object.
- /// @note Be careful about how this is used, since any operations on the
- /// returned value are inherently non-atomic.
- T load() const {
-#if defined(ATOMIC_USE_GCC_INTRINSICS)
- return __atomic_load_n(&value_, __ATOMIC_SEQ_CST);
-#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
- // TODO(m): Is there a better solution for MSVC?
- return value_;
-#else
- return value_;
-#endif
- }
-
- /// @brief Performs an atomic exchange operation.
- ///
- /// The value of the atomic object is unconditionally updated to the new
- /// value, and the old value is returned.
- ///
- /// @param new_val The new value to write to the atomic object.
- /// @returns the old value.
- T exchange(const T new_val) {
-#if defined(ATOMIC_USE_GCC_INTRINSICS)
- return __atomic_exchange_n(&value_, new_val, __ATOMIC_SEQ_CST);
-#elif defined(ATOMIC_USE_MSVC_INTRINSICS)
- return msvc::interlocked::exchange(&value_, new_val);
-#else
- return value_.exchange(new_val);
-#endif
- }
-
- T operator=(const T new_value) {
- store(new_value);
- return new_value;
- }
-
- operator T() const {
- return load();
- }
-
-private:
-#if defined(ATOMIC_USE_GCC_INTRINSICS) || defined(ATOMIC_USE_MSVC_INTRINSICS)
- volatile T value_;
-#else
- std::atomic value_;
-#endif
-
- ATOMIC_DISALLOW_COPY(atomic)
-};
-
-} // namespace atomic
-
-// Undef temporary defines.
-#undef ATOMIC_USE_GCC_INTRINSICS
-#undef ATOMIC_USE_MSVC_INTRINSICS
-#undef ATOMIC_USE_CPP11_ATOMIC
-
-#endif // ATOMIC_ATOMIC_H_
diff --git a/src/tl/tl/atomic/atomic_msvc.h b/src/tl/tl/atomic/atomic_msvc.h
deleted file mode 100644
index d17254f48..000000000
--- a/src/tl/tl/atomic/atomic_msvc.h
+++ /dev/null
@@ -1,238 +0,0 @@
-//-----------------------------------------------------------------------------
-// This is free and unencumbered software released into the public domain.
-//
-// Anyone is free to copy, modify, publish, use, compile, sell, or distribute
-// this software, either in source code form or as a compiled binary, for any
-// purpose, commercial or non-commercial, and by any means.
-//
-// In jurisdictions that recognize copyright laws, the author or authors of
-// this software dedicate any and all copyright interest in the software to the
-// public domain. We make this dedication for the benefit of the public at
-// large and to the detriment of our heirs and successors. We intend this
-// dedication to be an overt act of relinquishment in perpetuity of all present
-// and future rights to this software under copyright law.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-// For more information, please refer to
-//-----------------------------------------------------------------------------
-
-#ifndef ATOMIC_ATOMIC_MSVC_H_
-#define ATOMIC_ATOMIC_MSVC_H_
-
-// Define which functions we need (don't include ).
-extern "C" {
-short _InterlockedIncrement16(short volatile*);
-long _InterlockedIncrement(long volatile*);
-__int64 _InterlockedIncrement64(__int64 volatile*);
-
-short _InterlockedDecrement16(short volatile*);
-long _InterlockedDecrement(long volatile*);
-__int64 _InterlockedDecrement64(__int64 volatile*);
-
-char _InterlockedExchange8(char volatile*, char);
-short _InterlockedExchange16(short volatile*, short);
-long __cdecl _InterlockedExchange(long volatile*, long);
-__int64 _InterlockedExchange64(__int64 volatile*, __int64);
-
-char _InterlockedCompareExchange8(char volatile*, char, char);
-short _InterlockedCompareExchange16(short volatile*, short, short);
-long __cdecl _InterlockedCompareExchange(long volatile*, long, long);
-__int64 _InterlockedCompareExchange64(__int64 volatile*, __int64, __int64);
-};
-
-// Define which functions we want to use as inline intriniscs.
-#pragma intrinsic(_InterlockedIncrement)
-#pragma intrinsic(_InterlockedIncrement16)
-
-#pragma intrinsic(_InterlockedDecrement)
-#pragma intrinsic(_InterlockedDecrement16)
-
-#pragma intrinsic(_InterlockedCompareExchange)
-#pragma intrinsic(_InterlockedCompareExchange8)
-#pragma intrinsic(_InterlockedCompareExchange16)
-
-#pragma intrinsic(_InterlockedExchange)
-#pragma intrinsic(_InterlockedExchange8)
-#pragma intrinsic(_InterlockedExchange16)
-
-#if defined(_M_X64)
-#pragma intrinsic(_InterlockedIncrement64)
-#pragma intrinsic(_InterlockedDecrement64)
-#pragma intrinsic(_InterlockedCompareExchange64)
-#pragma intrinsic(_InterlockedExchange64)
-#endif // _M_X64
-
-namespace atomic {
-namespace msvc {
-template
-struct interlocked {
-};
-
-template
-struct interlocked {
- static inline T increment(T volatile* x) {
- // There's no _InterlockedIncrement8().
- char old_val, new_val;
- do {
- old_val = static_cast(*x);
- new_val = old_val + static_cast(1);
- } while (_InterlockedCompareExchange8(reinterpret_cast(x),
- new_val,
- old_val) != old_val);
- return static_cast(new_val);
- }
-
- static inline T decrement(T volatile* x) {
- // There's no _InterlockedDecrement8().
- char old_val, new_val;
- do {
- old_val = static_cast(*x);
- new_val = old_val - static_cast(1);
- } while (_InterlockedCompareExchange8(reinterpret_cast(x),
- new_val,
- old_val) != old_val);
- return static_cast(new_val);
- }
-
- static inline T compare_exchange(T volatile* x,
- const T new_val,
- const T expected_val) {
- return static_cast(
- _InterlockedCompareExchange8(reinterpret_cast(x),
- static_cast(new_val),
- static_cast(expected_val)));
- }
-
- static inline T exchange(T volatile* x, const T new_val) {
- return static_cast(_InterlockedExchange8(
- reinterpret_cast(x), static_cast(new_val)));
- }
-};
-
-template
-struct interlocked {
- static inline T increment(T volatile* x) {
- return static_cast(
- _InterlockedIncrement16(reinterpret_cast(x)));
- }
-
- static inline T decrement(T volatile* x) {
- return static_cast(
- _InterlockedDecrement16(reinterpret_cast(x)));
- }
-
- static inline T compare_exchange(T volatile* x,
- const T new_val,
- const T expected_val) {
- return static_cast(
- _InterlockedCompareExchange16(reinterpret_cast(x),
- static_cast(new_val),
- static_cast(expected_val)));
- }
-
- static inline T exchange(T volatile* x, const T new_val) {
- return static_cast(
- _InterlockedExchange16(reinterpret_cast(x),
- static_cast(new_val)));
- }
-};
-
-template
-struct interlocked {
- static inline T increment(T volatile* x) {
- return static_cast(
- _InterlockedIncrement(reinterpret_cast(x)));
- }
-
- static inline T decrement(T volatile* x) {
- return static_cast(
- _InterlockedDecrement(reinterpret_cast(x)));
- }
-
- static inline T compare_exchange(T volatile* x,
- const T new_val,
- const T expected_val) {
- return static_cast(
- _InterlockedCompareExchange(reinterpret_cast(x),
- static_cast(new_val),
- static_cast(expected_val)));
- }
-
- static inline T exchange(T volatile* x, const T new_val) {
- return static_cast(_InterlockedExchange(
- reinterpret_cast(x), static_cast(new_val)));
- }
-};
-
-template
-struct interlocked {
- static inline T increment(T volatile* x) {
-#if defined(_M_X64)
- return static_cast(
- _InterlockedIncrement64(reinterpret_cast(x)));
-#else
- // There's no _InterlockedIncrement64() for 32-bit x86.
- __int64 old_val, new_val;
- do {
- old_val = static_cast<__int64>(*x);
- new_val = old_val + static_cast<__int64>(1);
- } while (_InterlockedCompareExchange64(
- reinterpret_cast(x), new_val, old_val) !=
- old_val);
- return static_cast(new_val);
-#endif // _M_X64
- }
-
- static inline T decrement(T volatile* x) {
-#if defined(_M_X64)
- return static_cast(
- _InterlockedDecrement64(reinterpret_cast(x)));
-#else
- // There's no _InterlockedDecrement64() for 32-bit x86.
- __int64 old_val, new_val;
- do {
- old_val = static_cast<__int64>(*x);
- new_val = old_val - static_cast<__int64>(1);
- } while (_InterlockedCompareExchange64(
- reinterpret_cast(x), new_val, old_val) !=
- old_val);
- return static_cast(new_val);
-#endif // _M_X64
- }
-
- static inline T compare_exchange(T volatile* x,
- const T new_val,
- const T expected_val) {
- return static_cast(_InterlockedCompareExchange64(
- reinterpret_cast(x),
- static_cast(new_val),
- static_cast(expected_val)));
- }
-
- static inline T exchange(T volatile* x, const T new_val) {
-#if defined(_M_X64)
- return static_cast(
- _InterlockedExchange64(reinterpret_cast(x),
- static_cast(new_val)));
-#else
- // There's no _InterlockedExchange64 for 32-bit x86.
- __int64 old_val;
- do {
- old_val = static_cast<__int64>(*x);
- } while (_InterlockedCompareExchange64(
- reinterpret_cast(x), new_val, old_val) !=
- old_val);
- return static_cast(old_val);
-#endif // _M_X64
- }
-};
-} // namespace msvc
-} // namespace atomic
-
-#endif // ATOMIC_ATOMIC_MSVC_H_
diff --git a/src/tl/tl/atomic/spinlock.h b/src/tl/tl/atomic/spinlock.h
deleted file mode 100644
index 9e9653b04..000000000
--- a/src/tl/tl/atomic/spinlock.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//-----------------------------------------------------------------------------
-// This is free and unencumbered software released into the public domain.
-//
-// Anyone is free to copy, modify, publish, use, compile, sell, or distribute
-// this software, either in source code form or as a compiled binary, for any
-// purpose, commercial or non-commercial, and by any means.
-//
-// In jurisdictions that recognize copyright laws, the author or authors of
-// this software dedicate any and all copyright interest in the software to the
-// public domain. We make this dedication for the benefit of the public at
-// large and to the detriment of our heirs and successors. We intend this
-// dedication to be an overt act of relinquishment in perpetuity of all present
-// and future rights to this software under copyright law.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
-// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-// For more information, please refer to
-//-----------------------------------------------------------------------------
-
-#ifndef ATOMIC_SPINLOCK_H_
-#define ATOMIC_SPINLOCK_H_
-
-#include "atomic.h"
-
-namespace atomic {
-class spinlock {
-public:
- spinlock() : value_(0) {}
-
- /// @brief Acquire the lock (blocking).
- /// @note Trying to acquire a lock that is already held by the calling thread
- /// will dead-lock (block indefinitely).
- void lock() {
- while (!value_.compare_exchange(UNLOCKED, LOCKED))
- ;
- }
-
- /// @brief Release the lock.
- /// @note It is an error to release a lock that has not been previously
- /// acquired.
- void unlock() { value_.store(UNLOCKED); }
-
-private:
- static const int UNLOCKED = 0;
- static const int LOCKED = 1;
-
- atomic value_;
-
- ATOMIC_DISALLOW_COPY(spinlock)
-};
-
-class lock_guard {
-public:
- /// @brief The constructor acquires the lock.
- /// @param lock The spinlock that will be locked.
- explicit lock_guard(spinlock& lock) : lock_(lock) {
- lock_.lock();
- }
-
- /// @brief The destructor releases the lock.
- ~lock_guard() {
- lock_.unlock();
- }
-
-private:
- spinlock& lock_;
-
- ATOMIC_DISALLOW_COPY(lock_guard)
-};
-
-} // namespace atomic
-
-#endif // ATOMIC_SPINLOCK_H_
diff --git a/src/tl/tl/tlThreads.cc b/src/tl/tl/tlThreads.cc
index 671c28ddd..19ff4fa77 100644
--- a/src/tl/tl/tlThreads.cc
+++ b/src/tl/tl/tlThreads.cc
@@ -20,15 +20,17 @@
*/
-#if !defined(HAVE_QT) || defined(HAVE_PTHREADS)
-
#include "tlThreads.h"
#include "tlUtils.h"
#include "tlTimer.h"
+#include "tlSleep.h"
#include "tlLog.h"
#include "tlInternational.h"
#include