Upgrade: switch to C++23 (see #1245)

The Lumiera »Reference Platform« is now upgraded to Debian/Buster, which provides GCC-14 and Clang-20.
Thus the compiler support for C++20 language features seems solid enough, and C++23,
while still in ''experimental stage'' can be seen as a complement and addendum.

This changeset
 * upgrades the compile switches for the build system
 * provides all the necessary adjustments to keep the code base compilable

Notable changes:
 * λ-capture by value now requires explicit qualification how to handle `this`
 * comparison operators are now handled transparently by the core language,
   largely obsoleting boost::operators. This change incurs several changes
   to implicit handling rules and causes lots of ambiguities — which typically
   pinpoint some long standing design issues, especially related to MObjects
   and the ''time entities''. Most tweaks done here can be ''considered preliminary''
 * unfortunately the upgraded standard ''fails'' to handle **tuple-like** entities
   in a satisfactory way — rather an ''exposition-only'' concept is introduced,
   which applies solely to some containers from the STL, thereby breaking some
   very crucial code in the render entities, which was built upon the notion of
   ''tuple-like'' entities and the ''tuple protocol''. The solution is to
   abandon the STL in this respect and **provide an alternative implementation**
   of the `apply` function and related elements.
This commit is contained in:
Fischlurch 2025-06-18 16:50:19 +02:00
parent d888891d84
commit afa7ca2e4d
44 changed files with 1165 additions and 104 deletions

View file

@ -65,7 +65,7 @@ def defineBuildEnvironment():
env.Replace( CPPPATH =["#src"] # used to find includes, "#" means always absolute to build-root
, CPPDEFINES=['LUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines
, CCFLAGS='-Wall -Wextra -Wformat-security'
, CXXFLAGS='-std=gnu++17 -Wno-enum-compare'
, CXXFLAGS='-std=gnu++23 -Wno-enum-compare'
, CFLAGS='-std=gnu99'
)
env.Append(LINKFLAGS='-Wl,--no-undefined') # require every dependency is given on link, in the right order

View file

@ -115,7 +115,7 @@ namespace stage {
facade.reset ( // trigger loading of the GuiStarterPlugin...
new GuiRunner (
[=] (string* problemMessage)
[=,this] (string* problemMessage)
{ // will be invoked when the UI thread exits
closeGuiModule();
termNotification(problemMessage);

View file

@ -121,8 +121,8 @@ namespace lib {
~AllocationCluster () noexcept;
/** hard wired size of storage extents */
static size_t constexpr EXTENT_SIZ = 256;
static size_t constexpr max_size();
static constexpr size_t EXTENT_SIZ = 256;
static constexpr size_t max_size();
/* === diagnostics === */

View file

@ -293,17 +293,17 @@ namespace lib {
template<class FUN>
explicit
Local (FUN&& buildInstance)
Local (FUN&& _buildInstance)
{
__assert_compatible<MOC>();
__assert_compatible<typename SubclassFactoryType<FUN>::Subclass>();
temporarilyInstallAlternateFactory (origInstance_, origFactory_
,[=]()
{
mock_.reset (buildInstance());
return mock_.get();
});
,[this, buildInstance=forward<FUN> (_buildInstance)]
{
mock_.reset (buildInstance());
return mock_.get();
});
}
~Local()
{

View file

@ -44,6 +44,7 @@
#define LIB_META_TUPLE_CLOSURE_H
#include "lib/meta/function-closure.hpp"
#include "lib/meta/tuple-helper.hpp"
#include "lib/util.hpp"
#include <utility>
@ -140,7 +141,7 @@ namespace meta{
auto
operator() (RemainingParams remPar) const
{
return std::apply (unConst(this)->partialClosure_, remPar);
return apply (unConst(this)->partialClosure_, remPar);
};
CLO partialClosure_;

View file

@ -42,6 +42,7 @@
#include <tuple>
#include <utility>
#include <functional>
namespace util { // forward declaration
@ -78,6 +79,56 @@ namespace meta {
using disable_if_Tuple = lib::meta::disable_if<lib::meta::is_Tuple<std::remove_reference_t<TUP>>>;
namespace { // apply to tuple-like : helpers...
/** @internal invocation helper similar to C++17 — but preferring a custom `get` impl */
template<typename FUN, typename TUP, size_t...Idx>
constexpr decltype(auto)
__unpack_and_apply (FUN&& f, TUP&& tup, std::index_sequence<Idx...>)
{ // ▽▽▽ ADL
using std::get;
return std::invoke (std::forward<FUN> (f)
,get<Idx> (std::forward<TUP>(tup))...
);
}
/** @internal invoke a metafunction with \a FUN and all element types from \a TUP */
template<template<typename...> class META, class FUN, class TUP>
struct _InvokeMetafunTup
{
using Tupl = std::decay_t<TUP>;
using Elms = typename ElmTypes<Tupl>::Seq;
using Args = typename Prepend<FUN, Elms>::Seq;
using Type = typename RebindVariadic<META, Args>::Type;
};
template<class FUN, class TUP>
inline constexpr bool can_nothrow_invoke_tup = _InvokeMetafunTup<std::is_nothrow_invocable,FUN,TUP>::Type::value;
}
/**
* Replacement for `std::apply` yet applicable to _tuple-like custom types_.
* For unclear reasons, the standard chooses to reject such custom types, and
* only allows a fixed set of explicitly defined facilities from the Stdlib
* (tuple, pair, array, and some ranges stuff).
* @todo 6/2025 as a first step, this replicates the implementation from C++17;
* the second step would be to constrain this to a concept `tuple_like`
*/
template<class FUN, class TUP>
constexpr decltype(auto)
apply (FUN&& f, TUP&& tup) noexcept (can_nothrow_invoke_tup<FUN,TUP> )
{
using Indices = std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<TUP>>>;
return __unpack_and_apply (std::forward<FUN> (f)
,std::forward<TUP> (tup)
,Indices{}
);
}
/**
* Tuple iteration: perform some arbitrary operation on each element of a tuple.
* @note the given functor must be generic, since each position of the tuple
@ -87,7 +138,7 @@ namespace meta {
* then employ a fold expression with the comma operator.
*/
template<class TUP, class FUN, typename = enable_if_Tuple<TUP>>
void
constexpr void
forEach (TUP&& tuple, FUN fun)
{
std::apply ([&fun](auto&&... elms)
@ -112,7 +163,7 @@ namespace meta {
* is used, which is guaranteed to evaluate from left to right.
*/
template<class TUP, class FUN, typename = enable_if_Tuple<TUP>>
auto
constexpr auto
mapEach (TUP&& tuple, FUN fun)
{
return std::apply ([&fun](auto&&... elms)

View file

@ -31,6 +31,13 @@
** the corresponding operators on the pointee and by allowing to specify a base class smart-ptr
** as template parameter.
**
** @deprecated 2025 : smells like an overly zealous design, while fundamental traits of the
** involved entities remain nebulous. Who is the »entity«? The pointer or the pointee?
** Why do we even want to delegate relational operators, while we do not even know that
** the target supports them? And why to we need an virtual equality? If these objects have
** reference semantics, then a base class should compare the identity. And there should not
** be any ordering on such elements. So the whole motivation of rolling a specialised
** shard-ptr seems moot. /////////////////////////////////////////////////////TICKET #501 : clarify Placement and MObject identity
** @see asset.hpp
** @see custom-shared-ptr-test.cpp
** @see orderingofassetstest.cpp
@ -94,11 +101,11 @@ namespace lib {
private: /* === friend operators injected into enclosing namespace for ADL === */
//////////////////TICKET #932 Clang is unable to fill in the default template argument. Resolved in newer versions of Clang. Temporary workaround: add second parameter B
///////////////////TICKET #932 Clang is unable to fill in the default template argument. Resolved in newer versions of Clang. Temporary workaround: add second parameter B
template<typename _O_,typename B>
friend inline bool
operator== (P const& p, P<_O_, B> const& q) { return (p and q)? (*p == *q) : (!p and !q); }
///////////////////////TICKET #501 : clarify Placement and MObject identity
template<typename _O_,typename B>
friend inline bool
operator!= (P const& p, P<_O_, B> const& q) { return (p and q)? (*p != *q) : !(!p and !q); }

View file

@ -234,8 +234,8 @@ namespace lib {
return Tar{floor (val)};
}
} //----headroom to accommodate low probabilities
static size_t constexpr QUANTISER = 1 << 4 + util::ilog2 (Tar::maxVal()-Tar::minVal());
static double constexpr CAP_EPSILON = 1/(2.0 * QUANTISER);
static constexpr size_t QUANTISER = 1 << 4 + util::ilog2 (Tar::maxVal()-Tar::minVal());
static constexpr double CAP_EPSILON = 1/(2.0 * QUANTISER);
/** @internal draw from source of randomness */

View file

@ -147,7 +147,7 @@ namespace lib {
* elements of type \a TY in memory _with proper alignment_.
*/
template<typename TY>
size_t inline constexpr
inline constexpr size_t
reqSiz()
{
size_t quant = alignof(TY);
@ -159,7 +159,7 @@ namespace lib {
}
/** determine size of a reserve buffer to place with proper alignment */
size_t inline constexpr
inline constexpr size_t
alignRes (size_t alignment)
{
return positiveDiff (alignment, alignof(void*));

View file

@ -148,7 +148,7 @@ namespace lib {
Symbol& operator= (Symbol &&) = default;
explicit operator bool() const { return not empty(); }
bool empty() const { return *this == BOTTOM or *this == EMPTY; }
bool empty() const { return *this == BOTTOM.c() or *this == EMPTY.c(); }
size_t
length() const

View file

@ -285,7 +285,7 @@ namespace time {
Duration
FrameRate::duration() const
{
if (0 == *this)
if (HALTED > *this)
throw error::Logic ("Impossible to quantise to an zero spaced frame grid"
, error::LUMIERA_ERROR_BOTTOM_VALUE);

View file

@ -451,28 +451,28 @@ namespace time {
int
HmsTC::getSecs() const
{ /////////////////////////////////////////////////////////////////////////////////////////////////TICKET #750 we do not want numeric accessors her — rather we want Digxel members
return (raw_time_64(tpoint_) / TIME_SCALE_sec) % 60;
return (_raw (tpoint_) / TIME_SCALE_sec) % 60;
}
/** @deprecated 5/25 : no numeric computations in this class! use Digxel instead! */
int
HmsTC::getMins() const
{
return (raw_time_64(tpoint_) / TIME_SCALE_sec / 60) % 60;
return (_raw (tpoint_) / TIME_SCALE_sec / 60) % 60;
}
/** @deprecated 5/25 : no numeric computations in this class! use Digxel instead! */
int
HmsTC::getHours() const
{
return raw_time_64(tpoint_) / TIME_SCALE_sec / 60 / 60;
return _raw (tpoint_) / TIME_SCALE_sec / 60 / 60;
}
/** @deprecated 5/25 : no numeric computations in this class! use Digxel instead! */
double
HmsTC::getMillis() const
{
return (raw_time_64(tpoint_) / TIME_SCALE_ms) % 1000;
return (_raw (tpoint_) / TIME_SCALE_ms) % 1000;
}
/** */

View file

@ -191,7 +191,7 @@ namespace time {
static TimeValue buildRaw_(raw_time_64);
/** @internal diagnostics */
operator std::string () const;
explicit operator std::string() const;
/** @return is in-domain, not a boundary value */
bool isRegular() const;
@ -265,8 +265,6 @@ namespace time {
return *this;
}
/// Support mixing with plain 64bit int arithmetics
operator raw_time_64() const { return t_; }
/// Support for micro-tick precise time arithmetics
operator FSecs() const { return FSecs{t_, TimeValue::SCALE}; }
@ -342,7 +340,7 @@ namespace time {
);
/** @internal diagnostics */
operator std::string () const;
explicit operator std::string() const;
/** convenience start for time calculations */
TimeVar operator+ (TimeValue const& tval) const { return TimeVar(*this) + tval; }
@ -405,7 +403,7 @@ namespace time {
Offset stretchedByFloatFactor (double) const;
/** @internal diagnostics, indicating ∆ */
operator std::string () const;
explicit operator std::string() const;
// Supporting sign flip
Offset operator- () const;
@ -522,7 +520,7 @@ namespace time {
/** @internal diagnostics */
operator std::string () const;
explicit operator std::string() const;
/// Supporting backwards use as offset
Offset operator- () const;
@ -651,7 +649,7 @@ namespace time {
void accept (Mutation const&);
/** @internal diagnostics */
operator std::string () const;
explicit operator std::string() const;
/// Supporting extended total order, based on start and interval length
friend bool operator== (TimeSpan const& t1, TimeSpan const& t2) { return t1.t_==t2.t_ && t1.dur_==t2.dur_; }
@ -689,7 +687,10 @@ namespace time {
/** duration of one frame */
Duration duration() const;
operator std::string() const;
/** derive total ordering from base class */
std::strong_ordering operator<=>(FrameRate const&) const = default;
explicit operator std::string() const;
};
/** convenient conversion to duration in fractional seconds */

View file

@ -30,7 +30,7 @@
namespace util {
template<typename N>
inline bool constexpr
inline constexpr bool
isPow2 (N n)
{
return n > 0 and !(n & (n-1));

View file

@ -40,9 +40,9 @@ namespace std {// forward declarations to avoid pervasive includes
class set;
template<typename IT, typename V>
IT find (IT, IT, V const&);
constexpr IT find (IT, IT, V const&);
template<typename IT, typename V>
IT remove (IT, IT, V const&);
constexpr IT remove (IT, IT, V const&);
}
@ -57,21 +57,21 @@ namespace util {
template <class NUM>
inline int constexpr
inline constexpr int
sgn (NUM n)
{
return (n==0)? 0 :((n<0)? -1:+1 );
}
template <class N1, class N2>
inline N1 constexpr
inline constexpr N1
min (N1 n1, N2 n2)
{
return n2 < n1? N1(n2) : n1;
}
template <class N1, class N2>
inline N1 constexpr
inline constexpr N1
max (N1 n1, N2 n2)
{
return n1 < n2? N1(n2) : n1;
@ -79,7 +79,7 @@ namespace util {
/** cut a numeric value to be >=0 */
template <typename NUM>
inline NUM constexpr
inline constexpr NUM
noneg (NUM val)
{
return (0<val? val : 0);
@ -87,7 +87,7 @@ namespace util {
/** force a numeric to be within bounds, inclusively */
template <typename NUM, typename NB>
inline NUM constexpr
inline constexpr NUM
limited (NB lowerBound, NUM val, NB upperBound)
{
return min ( max (val, lowerBound)
@ -95,7 +95,7 @@ namespace util {
}
template <typename NUM, typename NB>
inline bool constexpr
inline constexpr bool
isLimited (NB lowerBound, NUM val, NB upperBound)
{
return lowerBound <= val
@ -103,7 +103,7 @@ namespace util {
}
template <typename UN, typename N2>
inline UN constexpr
inline constexpr UN
positiveDiff (N2 newVal, UN refVal)
{
return UN(newVal) > refVal? UN(newVal) - refVal

View file

@ -113,8 +113,8 @@ namespace ctrl {
: queue_{}
, dispatcher_{}
{
dispatcher_.connect(
[=]() {try {
dispatcher_.connect([=,this]
{try {
queue_.invoke();
}
catch (std::exception& problem)

View file

@ -85,7 +85,7 @@ namespace stage {
void
NotificationService::dispatchMsg (ID uiElement, lib::diff::GenNode&& uiMessage)
{
dispatch_->event ([=]()
dispatch_->event ([=,this]
{
ctrl::BusTerm::mark (uiElement, uiMessage);
});
@ -136,7 +136,7 @@ namespace stage {
void
NotificationService::mutate (ID uiElement, MutationMessage&& diff)
{
dispatch_->event ([=]()
dispatch_->event ([=,this]
{ // apply and consume diff message stored within closure
this->change (uiElement, move(unConst(diff)));
});

View file

@ -231,7 +231,7 @@ namespace widget {
ms_seconds_ebox.set_can_focus(true);
auto connect_motion_event = [=](Gtk::EventBox& guiElm, Field fieldID)
auto connect_motion_event = [=,this](Gtk::EventBox& guiElm, Field fieldID)
{
auto handlerSlot = bind (mem_fun(this, &TimeCode::field_motion_notify_event), fieldID);
guiElm.signal_motion_notify_event().connect (handlerSlot);
@ -249,7 +249,7 @@ namespace widget {
connect_motion_event (ms_seconds_ebox, MS_Seconds);
auto connect_button_press = [=](Gtk::EventBox& guiElm, Field fieldID)
auto connect_button_press = [=,this](Gtk::EventBox& guiElm, Field fieldID)
{
auto handlerSlot = bind (mem_fun(this, &TimeCode::field_button_press_event), fieldID);
guiElm.signal_button_press_event().connect (handlerSlot);
@ -267,7 +267,7 @@ namespace widget {
connect_button_press (ms_seconds_ebox, MS_Seconds);
auto connect_button_release = [=](Gtk::EventBox& guiElm, Field fieldID)
auto connect_button_release = [=,this](Gtk::EventBox& guiElm, Field fieldID)
{
auto handlerSlot = bind (mem_fun(this, &TimeCode::field_button_release_event), fieldID);
guiElm.signal_button_release_event().connect (handlerSlot);
@ -285,7 +285,7 @@ namespace widget {
connect_button_release (ms_seconds_ebox, MS_Seconds);
auto connect_scroll_event = [=](Gtk::EventBox& guiElm, Field fieldID)
auto connect_scroll_event = [=,this](Gtk::EventBox& guiElm, Field fieldID)
{
auto handlerSlot = bind (mem_fun(this, &TimeCode::field_button_scroll_event), fieldID);
guiElm.signal_scroll_event().connect (handlerSlot);
@ -303,7 +303,7 @@ namespace widget {
connect_scroll_event (ms_seconds_ebox, MS_Seconds);
auto connect_key_press = [=](Gtk::EventBox& guiElm, Field fieldID)
auto connect_key_press = [=,this](Gtk::EventBox& guiElm, Field fieldID)
{
auto handlerSlot = bind (mem_fun(this, &TimeCode::field_key_press_event), fieldID);
guiElm.signal_key_press_event().connect (handlerSlot);
@ -321,7 +321,7 @@ namespace widget {
connect_key_press (ms_seconds_ebox, MS_Seconds);
auto connect_key_release = [=](Gtk::EventBox& guiElm, Field fieldID)
auto connect_key_release = [=,this](Gtk::EventBox& guiElm, Field fieldID)
{
auto handlerSlot = bind (mem_fun(this, &TimeCode::field_key_release_event), fieldID);
guiElm.signal_key_release_event().connect (handlerSlot);
@ -339,7 +339,7 @@ namespace widget {
connect_key_release (ms_seconds_ebox, MS_Seconds);
auto connect_focus_gain = [=](Gtk::EventBox& guiElm, Field fieldID)
auto connect_focus_gain = [=,this](Gtk::EventBox& guiElm, Field fieldID)
{
auto handlerSlot = bind (mem_fun(this, &TimeCode::field_focus_gain_event), fieldID);
guiElm.signal_focus_in_event().connect (handlerSlot);
@ -357,7 +357,7 @@ namespace widget {
connect_focus_gain (ms_seconds_ebox, MS_Seconds);
auto connect_focus_loss = [=](Gtk::EventBox& guiElm, Field fieldID)
auto connect_focus_loss = [=,this](Gtk::EventBox& guiElm, Field fieldID)
{
auto handlerSlot = bind (mem_fun(this, &TimeCode::field_focus_loss_event), fieldID);
guiElm.signal_focus_out_event().connect (handlerSlot);
@ -1108,7 +1108,7 @@ namespace widget {
if (frames != 0 && frames * drag_accum < (_raw(current_time())))
{
// minus because up is negative in computer-land
pos = TimeValue (floor (pos - drag_accum * frames));
pos = TimeValue (floor (_raw(pos) - drag_accum * frames));
set (pos, false);
}
else

View file

@ -136,7 +136,7 @@ namespace workspace {
bool
DockArea::hasPanel (const int description_index)
{
return util::has_any (panels_, [=](panel::Panel* panel)
return util::has_any (panels_, [&](panel::Panel* panel)
{
return getPanelType(panel) == description_index;
});

View file

@ -131,7 +131,7 @@ namespace workspace {
bool
PanelManager::hasPanel (const int description_index)
{
return util::has_any (panels_, [=](panel::Panel* panel)
return util::has_any (panels_, [&](panel::Panel* panel)
{
return getPanelType(panel) == description_index;
});

View file

@ -356,7 +356,7 @@ namespace control {
runningLoop_ =
make_unique<DispatcherLoop>(
[=](string* problemIndicator)
[=,this](string* problemIndicator)
{ // when the Session thread ends....
SteamDispatcher::endRunningLoopState();
termNotification (problemIndicator);

View file

@ -307,6 +307,8 @@ namespace engine {
{
builder.emplaceParamDataBlock (&block(), turnoutSys);
}
///////////////OOO
Feed()= default;
};

View file

@ -37,7 +37,6 @@
#include "lib/p.hpp"
#include "lib/time/timevalue.hpp"
#include <boost/operators.hpp>
#include <string>
@ -69,8 +68,7 @@ namespace mobject {
*/
class MObject
: public Buildable,
util::NonCopyable,
boost::equality_comparable< MObject >
util::NonCopyable
{
protected:
typedef lib::time::Duration Duration;
@ -97,12 +95,21 @@ namespace mobject {
/** MObject self-test (usable for asserting) */
virtual bool isValid() const =0;
virtual Duration& getLength() =0; ////////////////////TICKET #448
virtual bool operator== (const MObject& oo) const =0; ///< needed for handling by lumiera::P
virtual Duration& getLength() =0; ///////////////////////////TICKET #448
/** needed for handling by lumiera::P
* @deprecated 2025 this seems not well motivated. lumiera::P was created
* to support comparisons, and now we do not know how to implement them,
* and thus we make the operation virtual. Are MObjects conceived as
* having value semantics? For reference semantics, comparing the
* »identity« should be sufficient
* @note 2025 changed to a predicate to cope with C++20 reversed operators.
*/
virtual bool isEquivalentTo (const MObject& oo) const =0; ////////////////////////////////////////TICKET #501 : clarify Placement and MObject identity
friend bool operator== (MObject const& o1, MObject const& o2) { return o1.isEquivalentTo(o2); }
protected:
virtual string initShortID() const =0;
};

View file

@ -31,9 +31,10 @@ namespace session {
/** default/fallback implementation of equality
* using literal object identity (same address).
* Required to enable handling by lumiera::P
* @deprecated 2025, see comment in MObject ////////////////////////////////////////////////////////////TICKET #501 : clarify Placement and MObject identity
*/
bool
AbstractMO::operator== (const MObject& oo) const
AbstractMO::isEquivalentTo (const MObject& oo) const
{
return (this == &oo);
}

View file

@ -59,7 +59,7 @@ namespace session {
return length_;
}
bool operator== (const MObject& oo) const;
bool isEquivalentTo (const MObject& oo) const override;
protected:
void

View file

@ -94,9 +94,9 @@ namespace play {
{
shutdown_initiated_ = true;
launchDetached ("Output shutdown supervisor"
,[=]{
bringDown (completedSignal);
});
,[=,this]{
bringDown (completedSignal);
});
}
}

View file

@ -59,7 +59,7 @@ namespace gear {
class EngineEvent
{
protected:
static size_t constexpr RAW_SIZ = 3;
static constexpr size_t RAW_SIZ = 3;
using Storage = std::array<int64_t, RAW_SIZ>;
template<class DAT>

View file

@ -82,9 +82,7 @@ namespace gear {
using lib::time::FSecs;
using lib::time::Time;
using std::atomic;
using std::memory_order::memory_order_relaxed;
using std::memory_order::memory_order_acquire;
using std::memory_order::memory_order_release;
using std::memory_order;
using std::chrono_literals::operator ""us;
using std::chrono::microseconds;
@ -129,8 +127,8 @@ namespace gear {
{
ThreadID expect_noThread; // expect no one else to be in...
return groomingToken_.compare_exchange_strong (expect_noThread, thisThread()
,memory_order_acquire // success also constitutes an acquire barrier
,memory_order_relaxed // failure has no synchronisation ramifications
,memory_order::acquire // success also constitutes an acquire barrier
,memory_order::relaxed // failure has no synchronisation ramifications
);
}
@ -145,7 +143,7 @@ namespace gear {
{ // expect that this thread actually holds the Grooming-Token
REQUIRE (groomingToken_.load(memory_order_relaxed) == thisThread());
const ThreadID noThreadHoldsIt;
groomingToken_.store (noThreadHoldsIt, memory_order_release);
groomingToken_.store (noThreadHoldsIt, memory_order::release);
}
/**

View file

@ -66,7 +66,7 @@ namespace gear {
work::performRandomisedSpin (size_t stepping, size_t randFact)
{
size_t degree = CONTEND_SOFT_FACTOR * (1+randFact) * stepping;
for (volatile size_t i=0; i<degree; ++i) {/*SPIN*/}
for (volatile size_t i=0; i<degree; ) { i=i+1; /*SPIN*/}
}
/**

View file

@ -197,7 +197,7 @@ namespace test{
for (uint i=0; i<cnt; ++i)
{
uint increment = rand_.i(MAX_RAND_INCMT);
queue.feed ([=]() { countConsumerCall(increment); });
queue.feed ([=,this]{ countConsumerCall(increment); });
producerSum += increment;
usleep (delay);
queue.invoke(); // NOTE: dequeue one functor added during our sleep

View file

@ -112,7 +112,7 @@ namespace test{
quant (int testPoint)
{
TimeVar quantised = this->gridLocal(TimeValue(testPoint));
return int(quantised);
return _raw(quantised);
}
};

View file

@ -101,7 +101,7 @@ namespace test{
CHECK (!(var < ref) );
CHECK ( (var > ref) );
raw_time_64 rat(var);
raw_time_64 rat = _raw(var);
CHECK (!(rat == ref) );
CHECK ( (rat != ref) );
CHECK ( (rat >= ref) );

View file

@ -62,9 +62,9 @@ namespace test{
{
TimeValue parsed = FMT::parse (timeSpec_, *grid_);
CHECK (parsed == expected, "parsing '%s' resulted in %s instead of %s"
, cStr(timeSpec_)
, cStr(Time(parsed))
, cStr(Time(expected)));
, timeSpec_.c_str()
, string{Time(parsed)}.c_str()
, string{Time(expected)}.c_str());
}
void

View file

@ -142,7 +142,7 @@ namespace test{
CHECK (var < Time::MAX);
CHECK (var > Time::MIN);
raw_time_64 raw (var);
raw_time_64 raw = _raw(var);
CHECK (raw == org);
CHECK (raw > org - two);

View file

@ -83,7 +83,7 @@ namespace test {
AssetManager& aMang = AssetManager::instance();
CHECK (aMang.getAsset (mm1->getID()) == mm2); // record of mm1 was replaced by mm2
CHECK (aMang.getAsset (mm2->getID()) == mm2);
CHECK (aMang.getAsset (mm2->getID()) == mm2); ////////////////////////TICKET #501 : clarify Placement and MObject identity
CHECK (aMang.known (mm1->getID()));
CHECK (aMang.known (mm2->getID()));

View file

@ -82,7 +82,7 @@ namespace test {
return element_;
}
operator string() const { return element_; }
operator string() const { return util::toString(element_); }
friend bool

View file

@ -68,7 +68,7 @@ namespace test {
{
Placement<Clip>& pC = getPlacement<Clip>();
cout << "Clip on media : "<< pC->getMedia() <<"\n";
CHECK (pC->operator==(c));
CHECK (pC->isEquivalentTo(c));
log_ = string (pC);
}
void treat (AbstractMO&)

View file

@ -22,8 +22,6 @@
#include "lib/p.hpp"
#include <boost/operators.hpp>
namespace lib {
@ -37,15 +35,13 @@ namespace test{
struct X
: boost::totally_ordered<X>
{
long x_;
X(long x=0) : x_(x) {}
explicit X(long x=0) : x_(x) {}
operator long () { return x_; }
bool operator< (const X& ox) const { return x_ < ox.x_; }
bool operator== (const X& ox) const { return x_ == ox.x_; }
std::strong_ordering operator<=>(X const&) const = default;
virtual ~X() {} // using RTTI
};

View file

@ -27,6 +27,7 @@
#include <string>
using lumiera::error::Fatal;
using lib::transformIterator;
using lib::iter_stl::snapshot;
using lib::iter_stl::eachElm;
@ -53,6 +54,12 @@ namespace test {
operator string() const { return "hey Joe!"; }
};
class Bomb
{
public:
operator string() const { throw Fatal{"mistake"}; }
};
class AutoCounter
@ -110,7 +117,7 @@ namespace test {
CHECK (toString (chatterer) == "hey Joe!"_expect);
CHECK (toString (&chatterer) == "↗hey Joe!"_expect); // pointer indicated
CHECK (toString (nullptr) == ""_expect); // runtime exception, caught
CHECK (toString (Bomb{}) == ""_expect); // runtime exception, caught
CHECK (toString (true) == "true"_expect); // special handling for bool
CHECK (toString (2+2 == 5) == "false"_expect);

View file

@ -660,7 +660,7 @@ namespace test {
*/
SessionThread(function<void(DiffSource*)> notifyGUI)
: ThreadJoinable{"BusTerm_test: asynchronous diff mutation"
, [=]
, [this,notifyGUI]
{
uint cnt = randGen_.i(MAX_RAND_BORGS);
for (uint i=0; i<cnt; ++i)
@ -719,8 +719,9 @@ namespace test {
usleep (100);
uiDispatcher.invoke();
}
session.join();
auto ok = session.join();
//------end-multithreaded-mutation---
CHECK (ok);
// on rare occasions we (consumer thread)
// prematurely empty the queue...

View file

@ -213,7 +213,7 @@ namespace test{
commandHandler_ = newHandler;
else
commandHandler_ =
[=](GenNode const& cmd)
[this](GenNode const& cmd)
{
log_.warn(_Fmt("NOT handling command-message %s in test-mode") % cmd);
};
@ -226,7 +226,7 @@ namespace test{
stateMarkHandler_ = newHandler;
else
stateMarkHandler_ =
[=](ID subject, GenNode const& mark)
[this](ID subject, GenNode const& mark)
{
log_.warn(_Fmt("NOT handling state-mark %s passed from %s in test-mode")
% mark % subject);

View file

@ -209,7 +209,7 @@ namespace test {
bool showRes = true; ///< print result data
bool showRef = true; ///< calculate single threaded reference time
static uint constexpr REPETITIONS{20};
static constexpr uint REPETITIONS{20};
BlockFlowAlloc bFlow{};
EngineObserver watch{};

View file

@ -1394,7 +1394,7 @@ namespace test {
for ( ; 0 < round; --round)
lib::hash::combine (scree,scree);
sink = scree;
sink++;
sink = sink + 1;
}
void
@ -1408,7 +1408,7 @@ namespace test {
for (size_t i=0; i<memBlock.size()-1; ++i)
memBlock[i+1] += memBlock[i];
sink = *memBlock.back();
sink++;
sink = sink + 1;
}
double

File diff suppressed because it is too large Load diff