diff --git a/admin/README.deb.lumiera.org.PUB.gpg b/admin/README.deb.lumiera.org.PUB.gpg new file mode 100644 index 000000000..de4eaa2b1 --- /dev/null +++ b/admin/README.deb.lumiera.org.PUB.gpg @@ -0,0 +1,5 @@ +This is the Public Key of the Package signing GPG key +used for building of Debian DEB packages on Lumiera.org + +Fingerprint: D0333C21252B66D54A4CC1D265B66B07A1DE94B2 +UID: Hermann Vosseler diff --git a/admin/build_lumiera-build-dependencies.sh b/admin/build_lumiera-build-dependencies.sh new file mode 100755 index 000000000..96fbf8a76 --- /dev/null +++ b/admin/build_lumiera-build-dependencies.sh @@ -0,0 +1,61 @@ +#!/bin/sh +# +# build_lumiera-build-dependencies.sh - prepare/build on a pristine Debian/Ubuntu system (Docker) +# +# +#------------------------------------------------------Setup +# The Debian DEB Depot to retrieve the source packages +DEBIAN_REPO="http://lumiera.org/debian/" +SRC_DISTRO="stretch" +REPO_SECTION="experimental" +# +# GPG pubkey to trust for signed packages +TRUSTED_GPG=$(dirname $0)/deb.lumiera.org.PUB.gpg +# +# Directory for building DEB packages +PACK_DIR=./pack +# +#------------------------------------------------------Setup(End) +# +fail() { + echo "\nFAIL: $1\n\n" + exit 1 +} + +# Sanity-Checks +[ -f $TRUSTED_GPG ] || fail "GPG Key not found: $TRUSTED_GPG" +mkdir -p $PACK_DIR +[ -w $PACK_DIR ] || fail "Unable to build. Can not write to $PACK_DIR" + + +# prepare the host system with Lumiera package sources +cp $TRUSTED_GPG /etc/apt/trusted.gpg.d/ +chmod a+r-x /etc/apt/trusted.gpg.d/$(basename $TRUSTED_GPG) +echo "deb-src $DEBIAN_REPO $SRC_DISTRO $REPO_SECTION" > /etc/apt/sources.list.d/55-lumiera.list + +apt update +apt install -y build-essential ca-certificates +apt update + +# build some special build dependencies from source +WORKDIR=$(pwd -P) +cd $PACK_DIR + +echo "\n\n======= building NoBug =======\n" +apt-get -y build-dep nobug +apt-get source --compile nobug +dpkg -i nobug-dev*deb libnobug*deb || fail "installing NoBug" +echo "\n\n======= building GDLmm =======\n" +apt-get -y build-dep libgdlmm-3-dev +apt-get source --compile libgdlmm-3-dev || fail "installing GDLmm" +dpkg -i libgdlmm-3*deb + +# install the build dependencies of Lumiera from DEB +echo "\n\nInstalling Lumiera build dependencies...\n" +apt-get -y build-dep lumiera + +# return to the working directory +cd $WORKDIR + +echo "Build-Dependencies of Lumiera successfully installed.\n\n" + diff --git a/admin/deb.lumiera.org.PUB.gpg b/admin/deb.lumiera.org.PUB.gpg new file mode 100644 index 000000000..6403dc3b6 Binary files /dev/null and b/admin/deb.lumiera.org.PUB.gpg differ diff --git a/admin/docker_open-lumiera-buildenv.sh b/admin/docker_open-lumiera-buildenv.sh new file mode 100755 index 000000000..2c245c209 --- /dev/null +++ b/admin/docker_open-lumiera-buildenv.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# +# docker_open-lumiera-buildenv.sh - launch Docker container with interactive build shell +# +# +#------------------------------------------------------Setup +# +# Working directory path on the host +WORKDIR_HOST="/home/$USER/devel/lumi" +# +# bind-mount of the working dir in the container +WORKDIR_GUEST="/lumi" +# +# Docker image-ID to launch +DOCKER_IMAGE="ubuntu:bionic" +# +# Script code to inject into interactive shell +COMMANDS=$(cat) <= 2.0 since a long time. Previously the buildsystem used to work with 1.0 - In addition, we use some SCons plug-ins, which are all shipped in-tree (`admin/scons`)] +* SCons *2.0* footnote:[we build with SCons >= 3.0 since a long time. However, since the times of 2.0, + there are no major breaking improvements we rely on -- so chances are that the Build works fine with + older versions. In addition, we use some SCons plug-ins, which are all shipped in-tree (`admin/scons`)] * pkg-config * Doxygen diff --git a/doc/technical/build/index.txt b/doc/technical/build/index.txt index 41a7dd76d..a6a2437b8 100644 --- a/doc/technical/build/index.txt +++ b/doc/technical/build/index.txt @@ -4,14 +4,14 @@ Lumiera build system As work progresses, we will add more information on the Lumiera build system. //Menu: label Build System -//Menu: prepend child 'Dependencies' +//Menu: prepend child 'BuildDependencies' //Menu: prepend child 'SCons' build -- continuous integration -- packaging * link:SCons.html[Buildsystem] -* link:Dependencies.html[Dependencies] +* link:BuildDependencies.html[Lumiera Build Dependencies] * link:BuildDroneDraft.html[»Builddrone« concept from 2008] * Packaging: link:LumieraDebianPackage.html[Debian] RPM * Lumiera link:../infra/debianDepot.html/[debian depot] diff --git a/doc/technical/code/c++11.txt b/doc/technical/code/c++11.txt index 2dd3a70a8..def4bb860 100644 --- a/doc/technical/code/c++11.txt +++ b/doc/technical/code/c++11.txt @@ -12,8 +12,8 @@ language and compiler support wasn't ready for what we consider _state of the cr amended deficiencies by rolling our own helper facilities, with a little help from Boost. Thus there was no urge for us to adopt the new language standard; we could simply wait for the compiler support to mature. In spring 2014, finally, we were able to switch our codebase -to C++11 with minimal effort.footnote:[since 8/2015 -- after the switch to Debian/Jessie -as a »reference platform«, we even compile with `-std=gnu++14`] +to C++11 with minimal effort.footnote:[since 2/2020 -- after the switch to Debian/Buster +as a »reference platform«, we even compile with `-std=gnu++17`] Following this switch, we're now able to reap the benefits of this approach; we may now gradually replace our sometimes clunky helpers and workarounds with the smooth syntax of the ``new language'' -- without being forced to learn or adopt @@ -201,28 +201,11 @@ August 2015:: our »reference system« (platform) is Debian/Jessie from now on. We have switched to **C\+\+14** and use (even require) GCC-4.9 or CLang 3.5 -- we can expect solid support for all C\+\+11 features and most C++14 features. +February 2020:: + our »reference system« (platform) is Debian/Buster from now on. + We have switched to **C\+\+17** and use (even require) GCC-8 or CLang 7 -- we can expect solid support + for all C\+\+17 features. -Perfect forwarding -~~~~~~~~~~~~~~~~~~ -Unfortunately, we ran into nasty problems with both GCC-4.7 and CLang 3.0 here, when chaining several forwarding calls. - -- the new _reference collapsing rules_ seem to be unreliably still. Note that even the standard library uses an - overload to implement `std::forward`, while in theory, a single definition should work for every case. -- in one case, the executable generated by GCC passed a reference to an temporary, where it should have - passed a rvalue reference (i.e. it should have _moved_ the temporary, instead of referring to the - location on stack) -- CLang is unable to pass a plain-flat rvalue through a chain of templated functions with rvalue references. - We get the inspiring error message ``binding of reference to type `std::basic_string` to a value of - type `std::basic_string` drops qualifiers'' - -Thus -- as of 9/2014 -- the _rules of the game_ are as folows - -- it is OK to take arguments by rvalue reference, when the type is explicit -- it is OK to use std::forward _once_ to pass-trough a templated argument -- but the _time is not yet ready_ to get rid of intermediary copies -- we still prefer returning by value (eligible for RVO) and copy-initialisation -- we refrain from switching our metaprogramming code from Loki-Typelists and hand-written specialisations - to variadic templates and `std::tuple` diff --git a/doc/technical/code/darkCorners.txt b/doc/technical/code/darkCorners.txt index 771ec6175..8e40f0831 100644 --- a/doc/technical/code/darkCorners.txt +++ b/doc/technical/code/darkCorners.txt @@ -7,46 +7,6 @@ nonportable hacks, terrorism and other misdemeanour_ Library ------- -Equality of Functors -~~~~~~~~~~~~~~~~~~~~ -One of the more important recent additions to the C++ language are function objects. -In addition to the features actually provided by the boost implementation, the tr1 report -also requires function instances to implement an equality operator. Unfortunately the -implementation approach choosen by boost makes a 100% correct implementation of -comparision very dificult, if not impossible. Thus, the boost developers refused -to implement this feature. - -The bad news is that really using the power of opaque function objects quickly drove -us (Lumiera) into a situation where such an equalty test and a hash calculation on -function objects would be necessary. The whole point of using function objects is -the ability to ``erase'' specific details, which has the downside that the resulting -generic objects are opaque and often dificult to manage, when it comes to storing -and retrieving objects building on such functors. - -Thus I built an hack, based on the implementation details of boost::function. -In +functor-util.hpp+ we define a +class HijackedFunction+, which has the same -data layout as the original boost::function. After forcibly casting such an function -(reference or pointer) into a +HijackedFunction+, we're able to inspect and evaluate -the implementation pointers for equality comparison and hash value calculation. -This approach works and actually detects copied functions to be _equal_, but is -unable to pinpoint _equivalence_, e.g. functors bound to the same function with -the same arguments through separate but otherwise identical invocations of +bind+. -Besides, should boost or the standard library implementors eventually change the -implementation, this workaround will break. - -post C++11 -^^^^^^^^^^ -As of this writing (1/2016), this still remains an unsolved issue. + -The new standard _does indeed require a comparison_, but only a comparison against -`nullptr`, which is equivalent to the `bool` conversion. It seems we need more. - -WARNING: what we have here is a really evil hack, and even the notion of ``equality'' - is not correct. We admit that real equality can not be achieved with something - like `std::function`, but in spite of that, we do have our own needs. - -[red]#TODO# investigate what we _really_ need and come up with a better concept... - - Binding Placeholders ~~~~~~~~~~~~~~~~~~~~ The standard allows function objects to be partially closed; this is achieved by diff --git a/doc/technical/howto/IdeSetup.txt b/doc/technical/howto/IdeSetup.txt index 9d52c4739..901e6e920 100644 --- a/doc/technical/howto/IdeSetup.txt +++ b/doc/technical/howto/IdeSetup.txt @@ -29,7 +29,7 @@ There is nothing really fancy with the configuration, things work as you'd expec actually enabled. This provider is used by the IDE to retrieve definitions from the compiler for syntax checks while you type and for building the search index. Typically, this provider is called ``GCC Builtin Compiler Settings''; please ensure in the global (or the project specific) configuration that the invocation command line includes - the argument `-std=gnu++14` -- otherwise you'll get a lot of red squiggles on the new language features ;-) + the argument `-std=gnu++17` -- otherwise you'll get a lot of red squiggles on the new language features ;-) Indexer troubleshooting ~~~~~~~~~~~~~~~~~~~~~~~ @@ -55,6 +55,20 @@ was able to see the right files with the right locations _manually_ -- more so if they are still accessible on the system. Dont blame the Indexer, which basically has no way to find out he is looking at the obsolete source files... +Sourcecode for relevant external libraries +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Especially when working on the GUI, it can be handy to have some of the most relevant libraries around: +`gdl`, `gdlmm3`, `glib2.0`, `glibmm2.4`, `gtk+3.0`, `gtkmm3.0`. Just extract the source code into a directory +and add it via the ``Makefile Project with Existing Code'' wizard. Of course it helps to some degree if you're +also able to _build_ that code (even partially) from within the IDE, since the indexer is than able to pick up +more cross linking information. However, this is not a strict requirement -- even while `F3` often fails, the +``Open Type'' dialog is able to spot the definition in many cases non the less, and when this fails, you can +still use ``brute-force'' file search. What turns out to be much more an impediment in practice is the fact +that you'll have to jump through that C++ binding layer, and you need to pick up some basic knowledge how +this layer works to wrap the underlying plain-C GTK entities; don't confuse the C++ _wrapper objects_ +with the _gobject_ (a concept from GLib) used by GTK. + + Debugger Breakpoints not working ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ This seems to be a FAQ since Eclipse Kepler: If some or all breakpoints just refuse to work and you see diff --git a/doc/user/tutorials/DebianBuilding.txt b/doc/user/tutorials/DebianBuilding.txt index ff679f08a..6c14be48a 100644 --- a/doc/user/tutorials/DebianBuilding.txt +++ b/doc/user/tutorials/DebianBuilding.txt @@ -37,7 +37,7 @@ should _not_ be done as root. . add a suitable source line to your *Apt configuration* ('/etc/apt/sources.lst') + ---- -deb-src https://lumiera.org/debian/ jessie experimental +deb-src https://lumiera.org/debian/ buster experimental ---- . get all the *build dependencies* + diff --git a/doc/user/tutorials/building.txt b/doc/user/tutorials/building.txt index e09f2dcd7..023bc10fa 100644 --- a/doc/user/tutorials/building.txt +++ b/doc/user/tutorials/building.txt @@ -1,6 +1,6 @@ Building Lumiera from source ============================ -:Date: 2013 +:Date: 2020 :toc: At the moment you can build Lumiera, start the standard Lumiera GUI and run the @@ -40,13 +40,13 @@ Requirements To build Lumiera, you'll need a _build environment_ together with the _development packages_ of the libraries Lumiera depends on. footnote:[there is a separate documentation page listing the -link:{ldoc}/technical/build/Dependencies.html[build dependencies] explicitly. +link:{ldoc}/technical/build/BuildDependencies.html[build dependencies] explicitly. We'll try to keep that information up to date -- but in the end, the really authoritative information about the build dependencies is encoded into the link:{ldoc}/technical/build/SCons.html[build system]. Thus, when the build system aborts, indicating that a never version of some library is required, then usually the build system is right...] -More specifically, you'll need the GNU C/C\++ compiler with C++14 support (Version >= 4.9) +More specifically, you'll need the GNU C/C\++ compiler with C++17 support (Version >= 7) in addition to the following tools and libraries: * link:http://git-scm.com/[Git] (version management system) @@ -63,12 +63,6 @@ The GUI depends on the following: * link:https://wiki.gnome.org/LibRsvg[lib rSVG] * link:https://git.gnome.org/browse/gdl[lib GDL] -CAUTION: there are known problems with *GCC-5.x* as of 11/2015 + - on recent distributions (Ubuntu/wily, Debian/stretch) you might - encounter failing tests.footnote:[these problems aren't really serious; - basically we're sometimes checking mangled class/type names, and seemingly - the mangling behaviour of GCC has changed slightly. We're working on that...] - TIP: Generally speaking, when you want to build software, you'll need the _development_ version of the packages that contain the headers and pre-built libraries to link against. These packages are usually named `-devel` or `-dev`. @@ -81,17 +75,6 @@ libboost-dev libboost-program-options-dev libboost-regex-dev libboost-filesystem libgavl-dev libgtkmm-3.0-dev libgdl-3-dev librsvg2-dev libxv-dev ------------------------------------------------------------------------------------- -Ubuntu note:: - some people reported you need to install the `intltool` package from the standard - Ubuntu repository (for this reason it is included in the above collection) -Mint-17.2 (Rafaela) and Ubuntu 12.LTS:: - we really need the gcc-4.9, so building on these platforms is a bit tricky. See our - link:{ldoc}/technical/howto/backporting.html#_building_on_mint_17_2_rafaela_8201_8212_8201_gcc_and_libstdc_4_9[»Backporting«] - page for detailed info... -GCC-5.0:: - we're aware of some changes in mangled names (or type-IDs), which cause some tests to fail. - Other than that, compilation worked for us. - Build Directory diff --git a/doc/user/tutorials/contributing.txt b/doc/user/tutorials/contributing.txt index 75d7bbb09..d3a5767c8 100644 --- a/doc/user/tutorials/contributing.txt +++ b/doc/user/tutorials/contributing.txt @@ -268,7 +268,6 @@ Steam Layer:: * implement a command dispatcher to allow blocking and queuing of commands * develop a scheme how to code the GUI commands in practice -- implement a symbol table for the `lib::Symbol` datatype - provide the foundation for symbolic rules and script bindings * expand on the work done for symbolic and hash references diff --git a/src/common/advice/binding.cpp b/src/common/advice/binding.cpp index 88c1f87f4..159948333 100644 --- a/src/common/advice/binding.cpp +++ b/src/common/advice/binding.cpp @@ -36,16 +36,16 @@ #include #include -#include +#include using lib::Literal; using util::isnil; -using boost::regex; -using boost::smatch; -using boost::sregex_iterator; -using boost::match_continuous; +using std::regex; +using std::smatch; +using std::sregex_iterator; +using std::regex_constants::match_continuous; using boost::hash_combine; using boost::lexical_cast; diff --git a/src/common/guifacade.cpp b/src/common/guifacade.cpp index 1b11bac13..0efed9e21 100644 --- a/src/common/guifacade.cpp +++ b/src/common/guifacade.cpp @@ -36,7 +36,6 @@ #include "lib/sync.hpp" #include "lib/error.hpp" #include "lib/depend.hpp" -#include "lib/functor-util.hpp" #include "common/instancehandle.hpp" #include "common/option.hpp" diff --git a/src/lib/cmdline.cpp b/src/lib/cmdline.cpp index 1d3015fc7..a0125562f 100644 --- a/src/lib/cmdline.cpp +++ b/src/lib/cmdline.cpp @@ -30,15 +30,14 @@ #include "lib/util.hpp" #include "include/logging.h" #include "lib/cmdline.hpp" +#include "lib/format-util.hpp" -#include -#include - -using boost::regex; -using boost::smatch; -using boost::regex_search; -using boost::algorithm::join; +#include +using std::regex; +using std::smatch; +using std::regex_search; +using util::join; using util::noneg; @@ -64,12 +63,12 @@ namespace lib { */ Cmdline::Cmdline (const string cmdline) { - regex tokendef("[^ \r\n\t]+"); + static regex TOKENDEF{"\\S+"}; smatch match; string::const_iterator it = cmdline.begin(); string::const_iterator end = cmdline.end(); - while (regex_search(it, end, match, tokendef)) + while (regex_search(it, end, match, TOKENDEF)) { string ss(match[0]); this->push_back(ss); diff --git a/src/lib/cmdline.hpp b/src/lib/cmdline.hpp index ec67eef25..70a8eb8e5 100644 --- a/src/lib/cmdline.hpp +++ b/src/lib/cmdline.hpp @@ -27,6 +27,7 @@ ** the referred data into a vector of strings. Thus `Cmdline` is a way to ** express explicitly on APIs that we are consuming commandline contents, ** and, moreover, it offers a way more sane interface to deal with those. + ** @see CmdlineWrapper_test */ diff --git a/src/lib/diagnostic-context.hpp b/src/lib/diagnostic-context.hpp index 0a0ba9045..c83feb1ef 100644 --- a/src/lib/diagnostic-context.hpp +++ b/src/lib/diagnostic-context.hpp @@ -31,13 +31,6 @@ ** be accessed from an enclosed scope as a per-thread stack. DiagnosticContext ** provides an controlled environment for adding diagnostic code on demand; typically ** to be configured such as to resolve into an empty class for release builds. - ** - ** As of 2/10, this is an experimental feature in evaluation. To start with, - ** I'll use it to solve the problem of providing a NoBug resource tracker handle - ** without tangling the object monitor code (sync.hpp) with low level, NoBug related - ** implementation details. - ** - ** @todo add the actual diagnostic content **/ @@ -47,9 +40,6 @@ #include "lib/error.hpp" #include "lib/nocopy.hpp" -#include "lib/thread-local.hpp" - -#include @@ -58,7 +48,7 @@ namespace lib { - /** + /** * Diagnostic data frame to collect specific information concerning a scope. * To be placed explicitly as an automatic (stack) variable. Provides a controlled * environment for hooking up diagnostic code. Within each thread, a stack of @@ -70,34 +60,33 @@ namespace lib { class DiagnosticContext : util::NonCopyable { - typedef ThreadLocalPtr ThreadLocalAccess; - typedef std::vector ValSequence; + using ValSequence = std::vector; const VAL value_; DiagnosticContext * const prev_; /** embedded thread local pointer * to the innermost context encountered */ - static ThreadLocalAccess& + static DiagnosticContext* & current() { - static ThreadLocalAccess accessPoint; + thread_local DiagnosticContext* accessPoint; return accessPoint; } public: DiagnosticContext(VAL const& value_to_log = VAL()) - : value_(value_to_log) - , prev_(current().get()) + : value_{value_to_log} + , prev_{current()} { - current().set (this); + current() = this; } ~DiagnosticContext() { - ASSERT (this == current().get()); - current().set (prev_); + ASSERT (this == current()); + current() = prev_; } @@ -110,7 +99,7 @@ namespace lib { static DiagnosticContext& access () { - DiagnosticContext* innermost = current().get(); + DiagnosticContext* innermost = current(); if (!innermost) throw lumiera::error::Logic ("Accessing Diagnostic context out of order; " "an instance should have been created within " @@ -120,20 +109,17 @@ namespace lib { /** snapshot of the current stack of diagnostic frames - * @return vector with all the payload values currently - * on the thread-local diagnostic stack. Might - * be empty. Values start with frame next to - * the current scope and end with outermost. + * @return vector with all the payload values currently on the thread-local diagnostic stack. + * Might be empty. Values start with frame next to the current scope and end with outermost. * @warning can be inefficient on very large stacks - * @todo benchmark and improve the data structure - * used for the snapshot. Vector is not - * an optimal choice here. + * @todo benchmark and improve the data structure used for the snapshot. + * Vector is not an optimal choice here. */ static ValSequence extractStack() { ValSequence loggedValues; - DiagnosticContext* next = current().get(); + DiagnosticContext* next = current(); while (next) { loggedValues.push_back (*next); diff --git a/src/lib/functor-util.hpp b/src/lib/functor-util.hpp deleted file mode 100644 index 4512d54d5..000000000 --- a/src/lib/functor-util.hpp +++ /dev/null @@ -1,190 +0,0 @@ -/* - FUNCTOR-UTIL.hpp - collection of helpers for dealing with functors and signals - - Copyright (C) Lumiera.org - 2008, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - - -/** @file functor-util.hpp - ** Collection of small helpers and utilities related to function objects. - ** - ** @todo combine with meta/function-closure.hpp and reorganise - ** @todo 2017 find out to what extent we still need that (looks obsolete) - ** - ** @see GuiSubsysDescriptor#start (guifacade.cpp) - ** @see MementoTie - ** @see functor-util-test.cpp - ** - */ - - - -#ifndef FUNCTOR_UTIL_H -#define FUNCTOR_UTIL_H - -#include "lib/hash-value.h" - -#include -#include - - - -namespace util { ////////////TODO: refactor namespace. But probably not directly into namespace lib. Needs some more consideration though - - using std::function; - using std::bind; - using std::placeholders::_1; - - namespace { // hiding some nasty details... - - using lib::HashVal; - using boost::hash_combine; - - /** - * This Class is used to bypass the access protection - * and break into the tr1::function implementation. - * Thus we can implement a raw comparison function, - * as a replacement for the missing functor comparison - * facility. (TR1 requires an operator==, but boost - * seemingly doesn't provide it, because it can't - * be done correctly/properly in all cases. See - * the section "FAQ" in the documentation of - * the boost/function library) - * - * The layout of this class is chosen to mimic that - * of the boost function implementation, without all - * the generic type decoration. For the comparison - * we use a conservative approach, by requiring - * the concrete invoker, the storage manager and - * the actual function and argument data pointers - * to be the same. - * @todo 2017 is this still necessary today? - */ - class HijackedFunction - : std::_Function_base - { - typedef void (*DummyInvoker) (void); - DummyInvoker invoker_; - - public: - - friend bool - operator== (HijackedFunction const& f1, - HijackedFunction const& f2) - { - return (f1.invoker_ == f2.invoker_) - && (f1._M_manager == f2._M_manager) - && (f1._M_functor._M_unused._M_const_object == - f2._M_functor._M_unused._M_const_object ); - } // note: we don't cover any member pointer offset - - friend HashVal - hash_value (HijackedFunction const& fun) - { - HashVal hash(0); - hash_combine (hash, fun.invoker_); - hash_combine (hash, fun._M_manager); - hash_combine (hash, fun._M_functor._M_unused._M_const_object); - return hash; // note: member pointer offset part uncovered - } - }; - - } - - - /** temporary workaround: tr1/functional should define - * public comparison operators for functor objects, but - * in the implementation provided by boost 1.34 it doesn't. - * To get at least \em some comparison capability, we do a - * brute force comparison of the functor's internal data. - * @note use with caution. This implementation relies on - * internal details of boost/function; but it is - * rather conservative and might deem functors - * "different" erroneously, due to garbage in - * the internal functor data's storage */ - template - inline bool - rawComparison (function const& f1, - function const& f2) - { - typedef HijackedFunction const& Hij; - - return reinterpret_cast (f1) - == reinterpret_cast (f2); - } - - /** catch-all for the comparison: functors with - * different base type are always "different" */ - template - inline bool - rawComparison (function const&, - function const&) - { - return false; - } - - /** variant with unchecked access */ - inline bool - rawComparison (void* f1, void* f2) - { - typedef HijackedFunction * HijP; - - return (!f1 && !f2) - || *reinterpret_cast (f1) - == *reinterpret_cast (f2); - } - - - /** workaround to calculate a hash value for a given function object. - * @note use with caution. This implementation relies on internal details - * of boost/function; it can be expected to be rather conservative, - * i.e. yielding different hash values for objects, which actually - * are semantically equivalent. - * @warning especially function objects bound to member functions aren't - * fully supported. It \em may happen that we miss differences on the - * offset part and only hash the "this" pointer on some platform. - */ - template - inline HashVal - rawHashValue (function const& fun) - { - typedef HijackedFunction const& Hij; - - return hash_value (reinterpret_cast (fun)); - } - -} // namespace util - -namespace std { - - /** inject into std::tr1 to be picked up by ADL: - * @return hash value of given functor - * @note use with caution. Hash is calculated - * relying on undocumented boost internals. - */ - template - inline lib::HashVal - hash_value (function const& fun) - { - return util::rawHashValue (fun); - } - -} - -#endif /*FUNCTOR_UTIL_H*/ diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index 781030e41..a4b5de54a 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -577,8 +577,9 @@ namespace lib { * series of new elements. Other layers might need to sync to this operation, and thus it is passed * down the chain. For that reason, we need a dedicated BaseAdapter to adsorb such chained calls. * @remark when building the TreeExplorer, the to-be-wrapped source is fed down into its place - * within BaseAdapter. For that reason, we need to lift the copy ctors of the base. - * Just inheriting the base class ctors won't do that, at least not in C++14. + * within BaseAdapter. For that reason, it is not sufficient just to lift the copy ctors + * of the base (as inheriting the base class ctors would do). Rather, we need dedicated + * further copy ctors to clone and move from the _undecorated base type._ */ template struct BaseAdapter diff --git a/src/lib/maybe.hpp b/src/lib/maybe.hpp deleted file mode 100644 index 27e315cca..000000000 --- a/src/lib/maybe.hpp +++ /dev/null @@ -1,122 +0,0 @@ -/* - MAYBE.hpp - dealing with optional values - - Copyright (C) Lumiera.org - 2011, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - - -/** @file maybe.hpp - ** Support for representation of optional values. - ** This implements a concept ("option monad") known from functional programming, - ** allowing to express the fact of some value possibly be unavailable. Using this - ** approach allows to avoid the dangerous technique of (ab)using NULL pointers to - ** represent missing values. - ** - ** While a NULL pointer carries this special meaning just by convention, marking a - ** parameter or return value as optional states this fact first class, and enforces - ** the necessary "is available" check through the type system. Surprisingly, this - ** leads not only to more secure, but also much more compact code, as we're now - ** able to substitute a fallback just by a "or else use this" clause. - ** Basically, there are different ways to access the actual value - ** - access through implicit conversion raises an exception for missing values - ** - evaluation as boolean allows to check, if the value is available - ** - an alternative or fallback value may be attached. - ** - ** @todo WIP and rather brainstorming as of 2/10 - ** @deprecated as of 2016 : the upcoming C++17 will provide an optional type!! - ** - ** @see vault::ThreadJob usage example - */ - - - -#ifndef LIB_MAYBE_H -#define LIB_MAYBE_H - -#include "lib/error.hpp" -//#include "lib/wrapper.hpp" -#include "lib/util.hpp" - -#include - - - -namespace lib { - - using util::isnil; - using std::string; - namespace error = lumiera::error; - - - namespace maybe { - - } - - - /** - * A value, which might be unavailable - * @throw error::State on any attempt to access a missing value - * without prior checking the availability - */ - template - class Maybe - { - VAL value_; - - public: - /** mark an invalid/failed result */ - Maybe () - { } - - /** standard case: valid result */ - Maybe (VAL const& value) - : value_(value) - { } - - - - bool - isValid() const - { - UNIMPLEMENTED ("check if optional value is available"); - } - - void - maybeThrow(Literal explanation =0) const - { - if (!isValid()) - throw error::State (explanation.empty()? "optional value not available" : string(explanation), - error::LUMIERA_ERROR_BOTTOM_VALUE); - } - - - VAL - get() const - { - maybeThrow(); - return value_; - } - }; - - - - - -} // namespace lib -#endif diff --git a/src/lib/meta/function-erasure.hpp b/src/lib/meta/function-erasure.hpp index 47764a6ea..6f41e78aa 100644 --- a/src/lib/meta/function-erasure.hpp +++ b/src/lib/meta/function-erasure.hpp @@ -58,7 +58,6 @@ #include "lib/util.hpp" #include "lib/error.hpp" #include "lib/opaque-holder.hpp" -#include "lib/functor-util.hpp" #include @@ -140,14 +139,6 @@ namespace meta{ { return get>(); } - - - friend bool - operator== (StoreFunction const& o1, - StoreFunction const& o2) - { - return util::rawComparison (o1.asBase(),o2.asBase()); - } }; @@ -179,16 +170,6 @@ namespace meta{ REQUIRE (fun); return *fun; } - - - friend bool - operator== (StoreFunPtr const& o1, - StoreFunPtr const& o2) - { - void * *fun1 = reinterpret_cast (o1.asBase()); - void * *fun2 = reinterpret_cast (o2.asBase()); - return *fun1 == *fun2; - } }; @@ -224,12 +205,6 @@ namespace meta{ explicit operator bool() const { return funP_; } bool isValid() const { return funP_; } - friend bool - operator== (StoreUncheckedFunPtr const& o1, - StoreUncheckedFunPtr const& o2) - { - return unConst(o1).funP_ == unConst(o2).funP_; - } }; diff --git a/src/lib/meta/function.hpp b/src/lib/meta/function.hpp index 1075c197c..5ac064e8d 100644 --- a/src/lib/meta/function.hpp +++ b/src/lib/meta/function.hpp @@ -129,6 +129,13 @@ namespace meta{ using Sig = RET(ARGS...); using Functor = std::function; }; + + /** Specialisation to strip `noexcept` from the signature */ + template + struct _Fun + : _Fun + { }; + /** Specialisation for using a function pointer */ template struct _Fun @@ -153,6 +160,12 @@ namespace meta{ : _Fun { }; + /** Specialisation to deal with member pointer to noexcept function */ + template + struct _Fun + : _Fun + { }; + /** Specialisation to handle member pointer to const function; * indirectly this specialisation also handles lambdas, * as redirected by the main template (via `decltype`) */ diff --git a/src/lib/meta/maybe-compare.hpp b/src/lib/meta/maybe-compare.hpp index 3564495ba..0cb56e408 100644 --- a/src/lib/meta/maybe-compare.hpp +++ b/src/lib/meta/maybe-compare.hpp @@ -30,15 +30,11 @@ #define LIB_META_MAYBE_COMPARE_H -#include "lib/functor-util.hpp" - -#include namespace lib { namespace meta{ - using std::function; /** * Trait template for invoking equality comparison. @@ -54,19 +50,7 @@ namespace meta{ } }; - /** while the boost function implementation doesn't provide comparison, - * we'll use our private hack, which at least detects equivalence - * in \em some cases... */ - template - struct Comparator> - { - static bool - equals (function const& f1, function const& f2) - { - return util::rawComparison(f1,f2); - } - - }; + /* == add specialisations here == */ template diff --git a/src/lib/meta/trait.hpp b/src/lib/meta/trait.hpp index ab396cc18..b534d8e5a 100644 --- a/src/lib/meta/trait.hpp +++ b/src/lib/meta/trait.hpp @@ -477,6 +477,18 @@ namespace meta { && HasFunSig_end::value }; }; + + struct is_noexcept_iterable + { + META_DETECT_NESTED(iterator); + META_DETECT_FUNCTION(typename X::iterator, begin,(void) noexcept); + META_DETECT_FUNCTION(typename X::iterator, end ,(void) noexcept); + + enum { value = HasNested_iterator::value + && HasFunSig_begin::value + && HasFunSig_end::value + }; + }; struct is_const_iterable { @@ -490,10 +502,24 @@ namespace meta { }; }; + struct is_const_noexcept_iterable + { + META_DETECT_NESTED(const_iterator); + META_DETECT_FUNCTION(typename X::const_iterator, begin,(void) const noexcept); + META_DETECT_FUNCTION(typename X::const_iterator, end ,(void) const noexcept); + + enum { value = HasNested_const_iterator::value + && HasFunSig_begin::value + && HasFunSig_end::value + }; + }; + public: enum { value = is_iterable::value - || is_const_iterable::value + or is_const_iterable::value + or is_noexcept_iterable::value + or is_const_noexcept_iterable::value }; }; @@ -516,6 +542,18 @@ namespace meta { }; }; + struct is_noexcept_backIterable + { + META_DETECT_NESTED(reverse_iterator); + META_DETECT_FUNCTION(typename X::reverse_iterator, rbegin,(void) noexcept); + META_DETECT_FUNCTION(typename X::reverse_iterator, rend ,(void) noexcept); + + enum { value = HasNested_reverse_iterator::value + && HasFunSig_rbegin::value + && HasFunSig_rend::value + }; + }; + struct is_const_backIterable { META_DETECT_NESTED(const_reverse_iterator); @@ -528,10 +566,24 @@ namespace meta { }; }; + struct is_const_noexcept_backIterable + { + META_DETECT_NESTED(const_reverse_iterator); + META_DETECT_FUNCTION(typename X::const_reverse_iterator, rbegin,(void) const noexcept); + META_DETECT_FUNCTION(typename X::const_reverse_iterator, rend ,(void) const noexcept); + + enum { value = HasNested_const_reverse_iterator::value + && HasFunSig_rbegin::value + && HasFunSig_rend::value + }; + }; + public: enum { value = is_backIterable::value - || is_const_backIterable::value + or is_const_backIterable::value + or is_noexcept_backIterable::value + or is_const_noexcept_backIterable::value }; }; diff --git a/src/lib/multifact.hpp b/src/lib/multifact.hpp index 24dab5128..aefd92f0f 100644 --- a/src/lib/multifact.hpp +++ b/src/lib/multifact.hpp @@ -47,12 +47,10 @@ ** ** @remarks this is the second attempt at building a skeleton of the core factory mechanics. ** The first attempt was pre-C++11, relied on partial specialisations and was hard to - ** understand and maintain. In theory, with C++11 the task should be quite simple now, - ** relying on rvalue references and variadic templates. Unfortunately, as of 9/2014, - ** the compiler support is not yet robust enough on Debian/stable really to deal with - ** \em all the conceivable cases when forwarding arbitrary factory products. Thus - ** for now we choose to avoid the "perfect forwarding" problem and rather let the - ** wrapper invoke the fabrication function and handle the result properly. + ** understand and maintain. Now, after C++11 the basic task was greatly simplified, + ** relying on rvalue references and variadic templates. However, we still need a + ** specialised factory template to allow for a _family of factory functions_ with + ** common configuration. ** ** @see multifact-test.cpp ** @see multifact-singleton-test.cpp diff --git a/src/lib/query-util.cpp b/src/lib/query-util.cpp index b370018d9..26bedbc1a 100644 --- a/src/lib/query-util.cpp +++ b/src/lib/query-util.cpp @@ -31,14 +31,15 @@ #include "lib/util.hpp" #include -#include +#include +#include #include using std::map; -using boost::regex; -using boost::smatch; -using boost::regex_search; -using boost::sregex_iterator; +using std::regex; +using std::smatch; +using std::regex_search; +using std::sregex_iterator; using util::contains; using util::isnil; @@ -49,7 +50,7 @@ namespace lib { namespace { // local definitions - typedef boost::function ChPredicate; + using ChPredicate = std::function ; ChPredicate is_alpha = boost::algorithm::is_alpha(); ChPredicate is_upper = boost::algorithm::is_upper(); @@ -79,14 +80,14 @@ namespace lib { map regexTable; - Literal matchArgument = "\\(\\s*([\\w_\\.\\-]+)\\s*\\),?\\s*"; - regex findPredicate (string("(\\w+)")+matchArgument); + Literal MATCH_ARGUMENT = R"~(\(\s*([\w_\.\-]+)\s*\),?\s*)~"; + const regex FIND_PREDICATE{string{"(\\w+)"} + MATCH_ARGUMENT}; inline regex& getTermRegex (Symbol sym) { if (!contains (regexTable, sym)) - regexTable[sym] = regex (string(sym)+matchArgument); + regexTable[sym] = regex (string(sym)+MATCH_ARGUMENT); return regexTable[sym]; } } @@ -146,7 +147,7 @@ namespace lib { { uint cnt (0); sregex_iterator end; - for (sregex_iterator i (q.begin(),q.end(), findPredicate); + for (sregex_iterator i (q.begin(),q.end(), FIND_PREDICATE); i != end; ++i) ++cnt; return cnt; diff --git a/src/lib/searchpath.cpp b/src/lib/searchpath.cpp index 5f20e7068..5f21460c6 100644 --- a/src/lib/searchpath.cpp +++ b/src/lib/searchpath.cpp @@ -43,6 +43,8 @@ namespace lib { LUMIERA_ERROR_DEFINE (FILE_NOT_DIRECTORY, "path element points at a file instead of a directory"); + using std::regex; + using std::regex_replace; const regex SearchPathSplitter::EXTRACT_PATHSPEC ("[^:]+"); @@ -78,7 +80,7 @@ namespace lib { static const string expandedOriginDir = fsys::path (findExePath()).parent_path().string() + "/"; ///////////TICKET #896 - return boost::regex_replace(src, PICK_ORIGIN_TOKEN, expandedOriginDir); + return regex_replace(src, PICK_ORIGIN_TOKEN, expandedOriginDir); } diff --git a/src/lib/searchpath.hpp b/src/lib/searchpath.hpp index 617552b63..c0633bd61 100644 --- a/src/lib/searchpath.hpp +++ b/src/lib/searchpath.hpp @@ -37,19 +37,15 @@ #include "lib/nocopy.hpp" #include -#include #include +#include namespace lib { using std::string; - using boost::regex; - using boost::smatch; - using boost::regex_search; - using boost::sregex_iterator; - typedef smatch::value_type const& SubMatch; + using SubMatch = std::smatch::value_type const&; namespace error = lumiera::error; namespace fsys = boost::filesystem; @@ -77,10 +73,10 @@ namespace lib { : util::NonCopyable { string pathSpec_; - sregex_iterator pos_, - end_; + std::sregex_iterator pos_, + end_; - static const regex EXTRACT_PATHSPEC; + static const std::regex EXTRACT_PATHSPEC; public: SearchPathSplitter (string const& searchPath) diff --git a/src/lib/sectionlock.h b/src/lib/sectionlock.h index 1e2f3e056..8ece0da10 100644 --- a/src/lib/sectionlock.h +++ b/src/lib/sectionlock.h @@ -31,7 +31,7 @@ #include -typedef int +typedef void (*lumiera_sectionlock_unlock_fn)(void*, struct nobug_flag* flag, struct nobug_resource_user** handle, const struct nobug_context ctx); diff --git a/src/lib/thread-local.hpp b/src/lib/thread-local.hpp deleted file mode 100644 index 98ef3832a..000000000 --- a/src/lib/thread-local.hpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - THREAD-LOCAL.hpp - support using thread local data - - Copyright (C) Lumiera.org - 2010, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/** @file thread-local.hpp - ** Helpers for working with thread local data. - ** As we don't want to depend on boost.threads, we'll provide some simple - ** support facilities for dealing with thread local data in RAII fashion. - ** Draft as of 2/10, to be extended on demand. - ** - ** @todo care for unit test coverage - ** @todo WIP-WIP. Maybe add facilities similar to boost::specific_ptr - ** @deprecated C++11 has a `thread_local` storage class... - **/ - - -#ifndef LIB_THREAD_LOCAL_H -#define LIB_THREAD_LOCAL_H - - -#include "lib/error.hpp" -#include "lib/nocopy.hpp" - -#include - - - -namespace lib { - - - /** - * Thread local pointer without ownership management. - * This (noncopyable) smart-ptr class cares for registering and - * deregistering the per-instance access key, but besides that - * behaves passively, like a normal pointer. When first accessed, - * the pointer is NIL in each new thread; it may be set by assignment. - */ - template - class ThreadLocalPtr - : util::NonCopyable - { - pthread_key_t key_; - - public: - ThreadLocalPtr() - { - if (pthread_key_create (&key_, NULL)) - throw lumiera::error::External ("unable to create key for thread local data"); - } - - ~ThreadLocalPtr() - { - WARN_IF (pthread_key_delete (key_), sync, "failure to drop thread-local data key"); - } - - explicit operator bool() const { return isValid(); } - - - bool isValid() const { return get(); } - TAR& operator* () const { return *accessChecked(); } - TAR* operator-> () const { return accessChecked(); } - - void operator= (TAR& tar) { set(&tar); } - - - TAR* - get() const - { - return static_cast (pthread_getspecific (key_)); - } - - void - set (TAR* pointee) - { - if (pthread_setspecific (key_, pointee)) - throw lumiera::error::External ("failed to store thread local data"); - } - - private: - TAR* - accessChecked() const - { - TAR *p(get()); - if (!p) - throw lumiera::error::State ("dereferencing a thread local NULL pointer" - ,lumiera::error::LERR_(BOTTOM_VALUE)); - return p; - } - - }; - - - -} // namespace lib -#endif diff --git a/src/lib/time/grid.hpp b/src/lib/time/grid.hpp index 50854ea30..f87dc0793 100644 --- a/src/lib/time/grid.hpp +++ b/src/lib/time/grid.hpp @@ -24,7 +24,7 @@ /** @file grid.hpp ** definition of a time grid abstraction for time and timecode handling. ** This interface is the foundation to deal with _quantised_ (grid aligned) - ** time values, as is essential for handling of timecode data. + ** time values, which is essential for handling of timecode data. */ @@ -43,12 +43,13 @@ namespace time { /** * Abstraction of a value alignment grid. * Such a grid has an underlying scale (origin and measurement) - * and is comprised of distinct grid intervals, which can be addressed - * by a ordering number, centred at origin with interval number zero. - * The typical example is a 25fps time frame grid, but indeed the - * spacing of the intervals is not necessarily constant. An entity - * defining such a grid provides functions to calculate the - * grid coordinates and to convert back to plain values. + * and is comprised of consecutive grid intervals, joined at the + * _grid points._ These can be addressed by an ordering number, + * centred at origin with grid point number zero. + * The classical example is a 25fps time frame grid, but in fact + * the length of the intervals is not necessarily constant. An + * entity defining such a grid provides functions to calculate + * the grid coordinates and to convert back to plain values. * This includes a way of rounding to the next lower * grid point, usable for grid aligning values. * diff --git a/src/lib/time/time.cpp b/src/lib/time/time.cpp index 76a988e5d..ce05c2cb6 100644 --- a/src/lib/time/time.cpp +++ b/src/lib/time/time.cpp @@ -55,6 +55,7 @@ extern "C" { #include #include #include +#include #include #include @@ -73,6 +74,9 @@ namespace error = lumiera::error; namespace lib { +namespace meta { + extern const std::string FAILURE_INDICATOR; +} namespace time { @@ -175,17 +179,30 @@ namespace time { } + namespace { + template + string + renderFraction (INT const& frac, Literal postfx) noexcept + try { + std::ostringstream buffer; + if (1 == frac.denominator() or 0 == frac.numerator()) + buffer << frac.numerator() << postfx; + else + buffer << frac < (numerator())+"FPS" - : lexical_cast (numerator()) - + "/" - + lexical_cast (denominator()) - + "FPS"; + return renderFraction (*this, "FPS"); } + /** @internal backdoor to sneak in a raw time value * bypassing any normalisation and limiting */ TimeValue @@ -247,6 +264,13 @@ namespace time { }} // namespace lib::Time +namespace util { + string + StringConv::invoke (lib::time::FSecs val) noexcept + { + return lib::time::renderFraction (val, "sec"); + } +} // namespace util @@ -285,7 +309,7 @@ lumiera_tmpbuf_print_time (gavl_time_t time) gavl_time_t lumiera_rational_to_time (FSecs const& fractionalSeconds) { - return rational_cast (lib::time::TimeValue::SCALE * fractionalSeconds); + return rational_cast (fractionalSeconds * int{lib::time::TimeValue::SCALE}); } gavl_time_t @@ -304,7 +328,7 @@ lumiera_frame_duration (FrameRate const& fps) throw error::Logic ("Impossible to quantise to an zero spaced frame grid" , error::LUMIERA_ERROR_BOTTOM_VALUE); - FSecs duration = rational_cast (1/fps); + FSecs duration = 1 / fps; return lumiera_rational_to_time (duration); } diff --git a/src/lib/time/timecode.cpp b/src/lib/time/timecode.cpp index a375d825d..a1f4ebee6 100644 --- a/src/lib/time/timecode.cpp +++ b/src/lib/time/timecode.cpp @@ -36,17 +36,17 @@ #include "lib/util.hpp" #include "lib/util-quant.hpp" +#include #include -#include #include -using std::string; using util::unConst; using util::isSameObject; using util::floorwrap; -using boost::regex; -using boost::smatch; -using boost::regex_search; +using std::string; +using std::regex; +using std::smatch; +using std::regex_search; using boost::lexical_cast; namespace error = lumiera::error; @@ -71,8 +71,8 @@ namespace time { TimeValue Frames::parse (string const& frameNumber, QuantR frameGrid) { - static regex frameNr_parser ("(? (match[1])); else @@ -119,17 +119,17 @@ namespace time { TimeValue Seconds::parse (string const& seconds, QuantR grid) { - static regex fracSecs_parser ("(? (match[N]) + #define SUB_EXPR(N) lexical_cast (match[N]) smatch match; if (regex_search (seconds, match, fracSecs_parser)) if (match[2].matched) { // complete spec with all parts FSecs fractionalPart (SUB_EXPR(2), SUB_EXPR(3)); - long fullSeconds (SUB_EXPR(1)); + int fullSeconds (SUB_EXPR(1)); return grid.timeOf (fullSeconds + fractionalPart); } else diff --git a/src/lib/time/timevalue.hpp b/src/lib/time/timevalue.hpp index a93691ad0..36c50c515 100644 --- a/src/lib/time/timevalue.hpp +++ b/src/lib/time/timevalue.hpp @@ -205,7 +205,7 @@ namespace time { /** rational representation of fractional seconds * @warning do not mix up gavl_time_t and FSecs */ - typedef boost::rational FSecs; + typedef boost::rational FSecs; /** @@ -550,12 +550,10 @@ namespace time { class FrameRate : public boost::rational { - typedef boost::rational IFrac; - public: FrameRate (uint fps) ; FrameRate (uint num, uint denom); - FrameRate (IFrac const& fractionalRate); + FrameRate (boost::rational const& fractionalRate); // standard copy acceptable; @@ -572,6 +570,13 @@ namespace time { operator std::string() const; }; + /** convenient conversion to duration in fractional seconds */ + inline FSecs + operator/ (int n, FrameRate rate) + { + return FSecs{ n*rate.denominator(), rate.numerator()}; + } + @@ -583,7 +588,7 @@ namespace time { inline NUM __ensure_nonzero (NUM n) { - if (n == 0) + if (n == NUM{0}) throw error::Logic ("Degenerated frame grid not allowed" , error::LERR_(BOTTOM_VALUE)); return n; @@ -614,17 +619,17 @@ namespace time { inline FrameRate::FrameRate (uint fps) - : IFrac (__ensure_nonzero(fps)) + : boost::rational (__ensure_nonzero(fps)) { } inline FrameRate::FrameRate (uint num, uint denom) - : IFrac (__ensure_nonzero(num), denom) + : boost::rational (__ensure_nonzero(num), denom) { } inline - FrameRate::FrameRate (IFrac const& fractionalRate) - : IFrac (__ensure_nonzero(fractionalRate)) + FrameRate::FrameRate (boost::rational const& fractionalRate) + : boost::rational (__ensure_nonzero(fractionalRate)) { } inline double @@ -647,5 +652,16 @@ namespace util { return 0 == dur; } + // repeated or forward declaration, see meta/util.hpp + template + struct StringConv; + + /** specialisation: render fractional seconds (for diagnostics) */ + template<> + struct StringConv + { + static std::string + invoke (lib::time::FSecs) noexcept; + }; } -#endif +#endif /*LIB_TIME_TIMEVALUE_H*/ diff --git a/src/steam/asset/media.cpp b/src/steam/asset/media.cpp index 33b2d2c68..0e4bef65d 100644 --- a/src/steam/asset/media.cpp +++ b/src/steam/asset/media.cpp @@ -38,7 +38,7 @@ #include "lib/util.hpp" #include "include/logging.h" -#include +#include using util::_Fmt; @@ -48,9 +48,9 @@ using lib::time::Duration; using backend_interface::MediaDesc; using backend_interface::MediaAccessFacade; -using boost::regex; -using boost::smatch; -using boost::regex_search; +using std::regex; +using std::smatch; +using std::regex_search; using std::dynamic_pointer_cast; namespace error = lumiera::error; @@ -66,10 +66,10 @@ namespace asset { */ string extractName (const string& path) { - regex pathname_pattern("([^/\\.]+)(\\.\\w+)?$"); + static regex PATHNAME_PATTERN("([^/\\.]+)(\\.\\w+)?$"); smatch match; - if (regex_search (path, match, pathname_pattern)) + if (regex_search (path, match, PATHNAME_PATTERN)) return util::sanitise (string (match[1])); else return ""; diff --git a/src/steam/control/command-closure.hpp b/src/steam/control/command-closure.hpp index 1951f1827..8d92a8617 100644 --- a/src/steam/control/command-closure.hpp +++ b/src/steam/control/command-closure.hpp @@ -112,7 +112,6 @@ namespace control { virtual operator string() const =0; virtual bool isValid () const =0; ///< does this closure hold a valid argument tuple? virtual bool isCaptured () const =0; ///< does this closure hold captured UNDO state? - virtual bool equals (CmdClosure const&) const =0; ///< is equivalent to the given other closure? virtual void bindArguments (Arguments&) =0; ///< store a set of parameter values within this closure virtual void bindArguments (lib::diff::Rec const&) =0; ///< store a set of parameter values, passed as GenNode sequence virtual void unbindArguments() =0; ///< discard any parameters and return to _unbound state_ diff --git a/src/steam/control/command-impl.hpp b/src/steam/control/command-impl.hpp index d1e06c8c0..437c7a8c4 100644 --- a/src/steam/control/command-impl.hpp +++ b/src/steam/control/command-impl.hpp @@ -29,8 +29,6 @@ ** identity and usually located within the (pooled) storage managed by the ** CommandRegistry. Client code gets access to a specific CommandImpl through ** a Command instance, which is a small (refcounting smart-ptr) handle. - ** - ** //TODO ** ** @see Command ** @see SteamDispatcher @@ -246,26 +244,6 @@ namespace control { % canUndo() % (pClo_? string(*pClo_) : util::FAILURE_INDICATOR); } - - - - friend bool - operator== (CommandImpl const& ci1, CommandImpl const& ci2) - { - return (ci1.do_ == ci2.do_) -// and (ci1.undo_ == ci2.undo_) // causes failure regularly, due to the missing equality on boost::function. See Ticket #294 - and (ci1.defaultPatt_ == ci2.defaultPatt_) - and (ci1.canExec() == ci2.canExec()) - and (ci1.canUndo() == ci2.canUndo()) - and (ci1.pClo_->equals(*ci2.pClo_)) - ; - } - - friend bool - operator!= (CommandImpl const& ci1, CommandImpl const& ci2) - { - return not (ci1==ci2); - } }; diff --git a/src/steam/control/command-mutation.hpp b/src/steam/control/command-mutation.hpp index 282443169..1184e9503 100644 --- a/src/steam/control/command-mutation.hpp +++ b/src/steam/control/command-mutation.hpp @@ -83,21 +83,6 @@ namespace control { LERR_(UNBOUND_ARGUMENTS)); clo.invoke (func_); } - - - - /// Supporting equality comparisons... - friend bool - operator== (Mutation const& m1, Mutation const& m2) - { - return (m1.func_ == m2.func_); - } - - friend bool - operator!= (Mutation const& m1, Mutation const& m2) - { - return not (m1==m2); - } }; diff --git a/src/steam/control/command-op-closure.hpp b/src/steam/control/command-op-closure.hpp index f97282a74..e04040482 100644 --- a/src/steam/control/command-op-closure.hpp +++ b/src/steam/control/command-op-closure.hpp @@ -64,7 +64,6 @@ namespace control { using lib::meta::NullType; using lib::meta::buildTuple; - using lib::meta::equals_safeInvoke; using lib::TypedAllocationManager; using std::function; using std::ostream; @@ -96,20 +95,11 @@ namespace control { /////////////////////////////////////////////////////////////TICKET #798 : we need to pick up arguments from a lib::diff::Record. - ostream& dump (ostream& output) const { return BASE::dump (output << element() << ','); } - - friend bool - compare (ParamAccessor const& p1, ParamAccessor const& p2) - { - return equals_safeInvoke (p1.element(), p2.element()) - && compare ( static_cast(p1) - , static_cast(p2) ); - } }; template @@ -135,12 +125,6 @@ namespace control { { return output; } - - friend bool - compare (ParamAccessor const&, ParamAccessor const&) - { - return true; - } }; @@ -218,11 +202,6 @@ namespace control { else return dumped+")"; } - - - /// Supporting equality comparisons... - friend bool operator== (OpClosure const& c1, OpClosure const& c2) { return compare (c1.params_, c2.params_); } - friend bool operator!= (OpClosure const& c1, OpClosure const& c2) { return not (c1 == c2); } }; diff --git a/src/steam/control/command-simple-closure.hpp b/src/steam/control/command-simple-closure.hpp index 0a64ec06f..dc10d49f5 100644 --- a/src/steam/control/command-simple-closure.hpp +++ b/src/steam/control/command-simple-closure.hpp @@ -204,30 +204,6 @@ namespace control { { arguments_.template create(); } - - - bool - equals (CmdClosure const& other) const override - { - const SimpleClosure* toCompare = dynamic_cast (&other); - return (toCompare) - and (*this == *toCompare); - } - - /// Supporting equality comparisons... - friend bool - operator== (SimpleClosure const& a1, SimpleClosure const& a2) - { - return (a1.arguments_->isValid() == a2.arguments_->isValid()) - and (*a1.arguments_ == *a2.arguments_) - ; - } - - friend bool - operator!= (SimpleClosure const& a1, SimpleClosure const& a2) - { - return not (a1 == a2); - } }; diff --git a/src/steam/control/command-storage-holder.hpp b/src/steam/control/command-storage-holder.hpp index e818f1c16..236c228a8 100644 --- a/src/steam/control/command-storage-holder.hpp +++ b/src/steam/control/command-storage-holder.hpp @@ -255,31 +255,6 @@ namespace control { { return memento_->getState(); } - - bool - equals (CmdClosure const& other) const - { - const StorageHolder* toCompare = dynamic_cast (&other); - return (toCompare) - and (*this == *toCompare); - } - - /// Supporting equality comparisons... - friend bool - operator== (StorageHolder const& a1, StorageHolder const& a2) - { - return (a1.arguments_->isValid() == a2.arguments_->isValid()) - && (*a1.arguments_ == *a2.arguments_) - && (a1.memento_->isValid() == a2.memento_->isValid()) - && (*a1.memento_ == *a2.memento_) - ; - } - - friend bool - operator!= (StorageHolder const& a1, StorageHolder const& a2) - { - return not (a1 == a2); - } }; diff --git a/src/steam/control/command.cpp b/src/steam/control/command.cpp index 2844408f4..9f09f10f5 100644 --- a/src/steam/control/command.cpp +++ b/src/steam/control/command.cpp @@ -369,13 +369,6 @@ namespace control { } - bool - Command::equivalentImpl (Command const& c1, Command const& c2) - { - return c1.impl() == c2.impl(); - } - - Symbol Command::getID() const noexcept { diff --git a/src/steam/control/command.hpp b/src/steam/control/command.hpp index daa298081..33f3dd5f2 100644 --- a/src/steam/control/command.hpp +++ b/src/steam/control/command.hpp @@ -32,8 +32,8 @@ ** function arguments need to be provided (this is called "binding" or "closing the function arguments"). ** These function arguments are stored within the command definition and remain opaque to the client code ** actually invoking the command. Behind the scenes, there is a CommandRegistry, holding an index of the - ** registered commands and managing the storage for command definitions and arguments. The actual - ** Command object used by client code is a small, copyable and ref-counting handle to this + ** registered commands and managing the storage for command definitions and arguments. The actual + ** Command object used by client code is a small, copyable and ref-counting handle to this ** stored definition backend. ** ** # Command definition, argument types and UNDO operation @@ -110,7 +110,7 @@ namespace control { * Handle object representing a single Command instance to be used by client code. * Commands are accessed \link #get through a symbolic ID \endlink; there needs to be * a CommandDef somewhere to specify the actual operation and to define, how the - * effect of the command can be undone. Moreover, the command's definition + * effect of the command can be undone. Moreover, the command's definition * refers to a HandlingPattern, which describes how the command is actually * to be executed (the default is scheduling it within the SteamDispatcher) * @@ -223,7 +223,6 @@ namespace control { private: void setArguments (Arguments&); void setArguments (lib::diff::Rec const&); - static bool equivalentImpl (Command const&, Command const&); }; @@ -312,9 +311,7 @@ namespace control { operator== (Command const& c1, Command const& c2) { return (!c1 && !c2) - || ( c1 && c2 && ( &c1.impl() == &c2.impl() - || Command::equivalentImpl (c1,c2) - )); + || ( c1 && c2 && (&c1.impl() == &c2.impl())); } inline bool @@ -328,7 +325,7 @@ namespace control { operator< (Command const& c1, Command const& c2) { return (!c1 && c2) - || ( c1 && c2 && (&c1.impl() < &c2.impl())); + || ( c1 && c2 && (&c1.impl() < &c2.impl())); } diff --git a/src/steam/control/memento-tie.hpp b/src/steam/control/memento-tie.hpp index 71535cf45..50f70f97a 100644 --- a/src/steam/control/memento-tie.hpp +++ b/src/steam/control/memento-tie.hpp @@ -44,7 +44,6 @@ #include "lib/meta/function-closure.hpp" #include "steam/control/command-signature.hpp" #include "lib/replaceable-item.hpp" -#include "lib/functor-util.hpp" #include "lib/format-obj.hpp" #include "lib/util.hpp" @@ -202,20 +201,6 @@ namespace control { /** for diagnostics: include format-util.hpp */ operator std::string() const; - - /// Supporting equality comparisons... - friend bool - operator== (MementoTie const& m1, MementoTie const& m2) - { - return ((!m1.undo_ && !m2.undo_ && !m1.capture_ && !m2.capture_) // either no valid functions - || ( util::rawComparison(m1.undo_, m2.undo_ ) // or identical functions - && util::rawComparison(m1.capture_,m2.capture_ ) - ) - ) - && (m1.isCaptured_ == m2.isCaptured_) // either both not captured or identical state - && (!m1.isCaptured_ - || equals_safeInvoke (m1.memento_, m2.memento_)); - } }; diff --git a/src/steam/engine/type-handler.hpp b/src/steam/engine/type-handler.hpp index 47359afd7..0eae6666f 100644 --- a/src/steam/engine/type-handler.hpp +++ b/src/steam/engine/type-handler.hpp @@ -28,7 +28,7 @@ ** "clean up" after usage. ** ** Within the Lumiera Engine, the BufferProvider default implementation utilises instances - ** of TypeHandler to \em describe specific buffer types capable of managing an attached object, + ** of TypeHandler to _describe specific buffer types_ capable of managing an attached object, ** or requiring some other kind of special treatment of the memory area used for the buffer. ** This BufferDescriptor is embodied into the BufferMetadata::Key and used later on to invoke ** the contained ctor / dtor functors, passing a concrete buffer (memory area). @@ -44,7 +44,6 @@ #include "lib/error.hpp" #include "lib/hash-value.h" -#include "lib/functor-util.hpp" #include #include @@ -84,6 +83,16 @@ namespace engine { X* embedded = static_cast (storageBuffer); embedded->~X(); } + + template + inline HashVal + deriveCombinedTypeIdenity() + { + HashVal hash{0}; + boost::hash_combine (hash, typeid(CTOR).hash_code()); + boost::hash_combine (hash, typeid(DTOR).hash_code()); + return hash; + } }//(End)placement-new helpers @@ -97,8 +106,14 @@ namespace engine { * special treatment of a buffer space. When defined, the buffer * will be prepared on locking and cleanup will be invoked * automatically when releasing. - * @warning comparison and hash values rely on internals of the - * std::function implementation and might not be 100% accurate + * @warning comparison and hash values are based merely on the type + * of the Ctor and Dtor functions -- so all type handlers bound + * to the same functor type count as equivalent. This might not + * be what you'd expect, however, there is no sane way to test + * for equivalence of functors anyway. In the typical usage, + * a TypeHandler will be created by TypeHandler::create(), + * and thus will be dedicated to a given type to be placed + * into the storage buffer. */ struct TypeHandler { @@ -106,11 +121,13 @@ namespace engine { DoInBuffer createAttached; DoInBuffer destroyAttached; + HashVal identity; /** build an invalid NIL TypeHandler */ TypeHandler() : createAttached() , destroyAttached() + , identity{0} { } /** build a TypeHandler @@ -124,6 +141,7 @@ namespace engine { TypeHandler(CTOR ctor, DTOR dtor) : createAttached (ctor) , destroyAttached (dtor) + , identity{deriveCombinedTypeIdenity()} { } /** builder function defining a TypeHandler @@ -154,22 +172,14 @@ namespace engine { friend HashVal hash_value (TypeHandler const& handler) { - HashVal hash(0); - if (handler.isValid()) - { - boost::hash_combine(hash, handler.createAttached); - boost::hash_combine(hash, handler.destroyAttached); - } - return hash; + return handler.identity; } friend bool operator== (TypeHandler const& left, TypeHandler const& right) { return (not left.isValid() and not right.isValid()) - || ( util::rawComparison(left.createAttached, right.createAttached) - && util::rawComparison(left.destroyAttached, right.destroyAttached) - ); + || (left.identity == right.identity); } friend bool operator!= (TypeHandler const& left, TypeHandler const& right) diff --git a/tests/25fundamental.tests b/tests/25fundamental.tests index ab68f6ecf..2de2bdb3e 100644 --- a/tests/25fundamental.tests +++ b/tests/25fundamental.tests @@ -125,11 +125,6 @@ return: 0 END -TEST "Wrapper thread-local pointers" ThreadLocal_test <= val && val > prev )) - throw error::Fatal ("thread-local diagnostic stack"); + for (uint val : sequence) + if (not (isOdd(val) and seed >= val and val > prev )) + throw error::Fatal ("thread-local diagnostic stack"); + else prev = val; - } } static VecI diff --git a/tests/basics/time/quantiser-basics-test.cpp b/tests/basics/time/quantiser-basics-test.cpp index e37445409..b1eb73b35 100644 --- a/tests/basics/time/quantiser-basics-test.cpp +++ b/tests/basics/time/quantiser-basics-test.cpp @@ -43,8 +43,8 @@ namespace test{ namespace { - const uint MAX_FRAMES = 25*500; - const uint DIRT_GRAIN = 50; + const int MAX_FRAMES = 25*500; + const int DIRT_GRAIN = 50; const FSecs F25(1,25); // duration of one PAL frame @@ -91,10 +91,10 @@ namespace test{ { FixedFrameQuantiser fixQ(25); - uint frames = (rand() % MAX_FRAMES); + int frames = (rand() % MAX_FRAMES); FSecs dirt = (F25 / (2 + rand() % DIRT_GRAIN)); - Time rawTime = Time(frames*F25) + Duration(dirt); ////////////////TICKET #939 : should better use 64bit base type for FSecs ?? + Time rawTime = Time(frames*F25) + Duration(dirt); CHECK (Time( frames *F25) <= rawTime); CHECK (Time((frames+1)*F25) > rawTime); diff --git a/tests/basics/time/time-parsing-test.cpp b/tests/basics/time/time-parsing-test.cpp index 1f2cbf284..3a20977cf 100644 --- a/tests/basics/time/time-parsing-test.cpp +++ b/tests/basics/time/time-parsing-test.cpp @@ -144,6 +144,7 @@ namespace test{ Parsing ("xxx25#xxx") .should_yield (1); Parsing ("12 25#") .should_yield (1); Parsing ("12 25# 33#") .should_yield (1); // note pitfall: the first valid number is used + Parsing ("12 25# \n 33#") .should_yield (1); Parsing ("12\n 25# \n 33#") .should_yield (1); Parsing ("12.25#") .should_fail(); // rejected because of leading dot (ambiguity) } diff --git a/tests/core/steam/asset/meta/time-grid-basics-test.cpp b/tests/core/steam/asset/meta/time-grid-basics-test.cpp index 54f77303e..70578ebdc 100644 --- a/tests/core/steam/asset/meta/time-grid-basics-test.cpp +++ b/tests/core/steam/asset/meta/time-grid-basics-test.cpp @@ -52,8 +52,8 @@ namespace test { namespace { // Test definitions... - const Time testOrigin (12,34); - const FrameRate testFps (5,6); + const Time TEST_ORIGIN (12,34); + const FrameRate TEST_FPS (5,6); const uint MAX_FRAMES = 1000; const uint DIRT_GRAIN = 50; @@ -89,8 +89,8 @@ namespace test { CHECK ( spec.origin == TimeValue(0)); CHECK (!spec.predecessor); - spec.fps = testFps; - spec.origin = testOrigin; + spec.fps = TEST_FPS; + spec.origin = TEST_ORIGIN; PGrid myGrid = spec.commit(); CHECK (myGrid); @@ -101,15 +101,15 @@ namespace test { int randomFrame = (rand() % MAX_FRAMES); Time point (myGrid->timeOf (randomFrame)); - CHECK (point == testOrigin + randomFrame * testFps.duration()); + CHECK (point == TEST_ORIGIN + randomFrame * TEST_FPS.duration()); - uint fract = 2 + rand() % DIRT_GRAIN; - FSecs dirt = rational_cast (1 / testFps / fract); - ASSERT (Time(dirt) < testFps.duration()); + int fract = 2 + rand() % DIRT_GRAIN; + FSecs dirt = (1/TEST_FPS) / fract; + ASSERT (Time(dirt) < TEST_FPS.duration()); ASSERT (0 < dirt); Time dirty(point + Time(dirt)); - CHECK (point == testOrigin + myGrid->gridAlign(dirty)); + CHECK (point == TEST_ORIGIN + myGrid->gridAlign(dirty)); } diff --git a/tests/core/steam/control/command-argument-test.cpp b/tests/core/steam/control/command-argument-test.cpp index ba3b39c80..1b6a4155b 100644 --- a/tests/core/steam/control/command-argument-test.cpp +++ b/tests/core/steam/control/command-argument-test.cpp @@ -213,7 +213,6 @@ namespace test { Tracker::instanceCnt = 0; createTuples (testTuples); - checkArgumentComparison (); serialiseArgTuples (testTuples); testTuples.clear(); @@ -291,50 +290,6 @@ namespace test { - /** @test verify the comparison operators */ - void - checkArgumentComparison () - { - StorageHolder one, two; - CHECK (one == two); // empty, identically typed argument holders -->equal - - one.tie(dummyU,dummyC) - .tieCaptureFunc()(1,9); - CHECK (one != two); // now one contains captured UNDO state - - two.tie(dummyU,dummyC) - .tieCaptureFunc()(1,9); - two.memento() = one.memento(); // put the same UNDO state in both - CHECK (one == two); // ...makes them equal again - - one.storeTuple (make_tuple (1,2)); - CHECK (one != two); // verify argument tuple comparison - CHECK (two != one); - CHECK (!isnil (one)); - CHECK ( isnil (two)); - - two.storeTuple (make_tuple (3,4)); - CHECK (!isnil (two)); - CHECK (one != two); - CHECK (two != one); - - one.storeTuple (make_tuple (1,4)); - CHECK (!isnil (one)); - CHECK (one != two); - CHECK (two != one); - - one.storeTuple (make_tuple (3,4)); - CHECK (!isnil (one)); - CHECK (one == two); - CHECK (two == one); - two.memento() = 12345; - CHECK (!isnil (two)); - CHECK (one != two); - CHECK (two != one); - } - - - /** @test simulate a complete command lifecycle with regards to the * storage handling of the command parameters and state memento. */ diff --git a/tests/core/steam/control/command-clone-builder-test.cpp b/tests/core/steam/control/command-clone-builder-test.cpp index bccb0df22..27d399b17 100644 --- a/tests/core/steam/control/command-clone-builder-test.cpp +++ b/tests/core/steam/control/command-clone-builder-test.cpp @@ -137,7 +137,6 @@ namespace test { CHECK (orig && copy); CHECK (orig->canExec()); CHECK (copy->canExec()); - CHECK (orig == copy); // prepare for command invocation on implementation level.... @@ -151,13 +150,11 @@ namespace test { long state_after_exec1 = command1::check_; CHECK (command1::check_ > 0); CHECK (orig->canUndo()); - CHECK (orig != copy); CHECK (!copy->canUndo()); testExec.exec (*copy, "Execute clone"); // EXEC 2 CHECK (command1::check_ != state_after_exec1); CHECK (copy->canUndo()); - CHECK (copy != orig); // invoke UNDO on the clone testExec.undo (*copy, "Undo clone"); // UNDO 2 @@ -166,8 +163,6 @@ namespace test { // invoke UNDO on original testExec.undo (*orig, "Undo original"); // UNDO 1 CHECK (command1::check_ ==0); - - CHECK (copy != orig); } }; diff --git a/tests/core/steam/control/command-equality-test.cpp b/tests/core/steam/control/command-equality-test.cpp index 963bee5d5..513a21abf 100644 --- a/tests/core/steam/control/command-equality-test.cpp +++ b/tests/core/steam/control/command-equality-test.cpp @@ -98,30 +98,15 @@ namespace test { /*************************************************************************************//** * @test cover command equality detection. - * Two commands are deemed equivalent, if they - * - build on the same Mutation functors - * - are either both incomplete or - * - are bound to equivalent arguments - * - hold equivalent undo state (memento) - * To conduct this test, we set up two sets of functions, and then build both complete - * command objects and command implementation facilities based on them. - * - * @note The hidden problem with those comparisons is the equivalence of function objects. - * While required by TR1, unfortunately lib boost refuses to implement functor equality. - * Which forces us to resort to a low level hack, based on internals of the boost function - * implementation. This workaround reliably pinpoints differing functions, but sometimes - * fails to detect equivalent functions under specific circumstances (e.g. when there is - * binding involved, and / or the binders have been cloned). Bottom line: \c == is - * reliable, \c != might be wrong. + * Two commands are deemed equivalent, if they are based on the same CommandImpl record. + * This means, we only rely on the _identity_ of those commands, but do not check the + * _equivalence_ of their backing implementations. The latter can not be possibly + * implemented in a totally airtight fashion, and for this reason, the C++ standard + * decided not to support comparison between std::function objects. * * @see control::Command - * @see control::CmdClosure - * @see control::Mutation - * @see control::UndoMutation - * @see control::MementoTie * @see control::CommandImpl * @see command-basic-test.hpp - * @see functor-util.hpp functor equality workaround */ class CommandEquality_test : public Test { @@ -133,148 +118,6 @@ namespace test { CHECK (&capt_1 != &capt_2); CHECK (&undo_1 != &undo_2); - verifyMutationEquality(); - verifyMementoEquality(); - verifyClosureEquality(); - verifyCommandEquality(); - } - - - - void - verifyMutationEquality() - { - Fun_o oFun_1 (oper_1); - Fun_o oFun_2 (oper_2); - Fun_o oFun_empty; - - Fun_u uFun_1 (undo_1); - Fun_u uFun_empty; - - Mutation mut1 (oFun_1); - Mutation muti (oFun_1); - Mutation mut2 (oFun_2); - CHECK (mut1 == mut1); - CHECK (mut1 == muti); - CHECK (muti == mut1); - CHECK (mut1 != mut2); - CHECK (mut2 != mut1); - CHECK (muti != mut2); - CHECK (mut2 != muti); - - Mutation umu (oFun_empty); // empty operation function - CHECK (mut1 != umu); - - Mutation mut_u0 (uFun_empty); // empty undo function - CHECK (mut_u0 != umu); - CHECK (mut_u0 != muti); - - Mutation mut_u1 (uFun_1); - CHECK (mut_u0 != mut_u1); // function signatures differing - } - - - void - verifyClosureEquality() - { - ArgHolder a1 (make_tuple ('a')); - ArgHolder a2 (make_tuple ('a')); - ArgHolder a3 (make_tuple ('z')); - CHECK (a1 == a1); - CHECK (a1 == a2); - CHECK (a2 == a1); - CHECK (a1 != a3); - CHECK (a3 != a1); - CHECK (a2 != a3); - CHECK (a3 != a2); - - typedef StorageHolder Storage; - Storage abuff1; - Storage abuff2; - CHECK (abuff1 == abuff2); - - TypedArguments newArgs (make_tuple ('z')); - abuff1.bindArguments(newArgs); - CHECK (abuff1 != abuff2); - abuff2.bindArguments(newArgs); - CHECK (abuff1 == abuff2); - UndoMutation umu1 (abuff1.tie (undo_1, capt_1)); - CHECK (abuff1 != abuff2); // abuff2 isn't tied yet, i.e. has no undo/capture function - UndoMutation umu2 (abuff2.tie (undo_1, capt_1)); - CHECK (abuff1 == abuff2); // same capture function, no memento state! - - Closure args {make_tuple ('u')}; - umu1.captureState(args); - CHECK (abuff1 != abuff2); - umu2.captureState(args); - CHECK (abuff1 == abuff2); // same functions, same memento state - - check_ += "fake"; // manipulate the "state" to be captured - umu2.captureState(args); // capture again... - CHECK (abuff1 != abuff2); // captured memento differs! - - UndoMutation umu3 (abuff2.tie (undo_1, capt_2)); - umu3.captureState(args); - CHECK (abuff1 != abuff2); // differing functions detected - } - - - void - verifyMementoEquality() - { - Fun_u uFun_1 (undo_1); - Fun_u uFun_2 (undo_2); - Fun_c cFun_1 (capt_1); - Fun_c cFun_2 (capt_2); - Fun_c cFun_empty; - - Fun_c empty_c; - - MemHolder m11 (uFun_1, cFun_1); - MemHolder m12 (uFun_1, cFun_2); - MemHolder m21 (uFun_2, cFun_empty); // note: unbound capture function - MemHolder m22 (uFun_2, cFun_2); - - CHECK (m11 == m11); - CHECK (m12 == m12); - CHECK (m21 == m21); - CHECK (m22 == m22); - CHECK (!(m11 != m11)); - - CHECK (m11 != m12); - CHECK (m11 != m21); - CHECK (m11 != m22); - CHECK (m12 != m11); - CHECK (m12 != m21); - CHECK (m12 != m22); - CHECK (m21 != m11); - CHECK (m21 != m12); - CHECK (m21 != m22); - CHECK (m22 != m11); - CHECK (m22 != m12); - CHECK (m22 != m21); - - MemHolder m22x (m22); // clone copy - CHECK (!m22x); - CHECK (m22 == m22x); // same functions, no state --> equal - - m22x.tieCaptureFunc() ('x'); // produce a memento state - CHECK (!isnil (m22x.getState())); - - CHECK (m22 != m22x); - m22.tieCaptureFunc() ('x'); // get same value into the memento within m22 - CHECK (m22 == m22x); - - // document shortcomings on UndoMutation comparisons - UndoMutation umu11 (m11); - UndoMutation umu12 (m11); // note: due to cloning the embedded functor, - CHECK (umu11 != umu12); // our hacked-in comparison operator fails - } - - - void - verifyCommandEquality() - { CommandDef (COMMAND1) .operation (oper_1) .captureUndo (capt_1) diff --git a/tests/core/steam/control/command-registry-test.cpp b/tests/core/steam/control/command-registry-test.cpp index 8137fe36a..364b46b16 100644 --- a/tests/core/steam/control/command-registry-test.cpp +++ b/tests/core/steam/control/command-registry-test.cpp @@ -60,7 +60,7 @@ namespace test { * interface. Add/remove a command instance to the index, allocate an * CommandImpl frame and verify it is removed properly on ref count zero. * @note this test covers the internal bits of functionality, - * not the behaviour of the (integrated) command framework + * not the behaviour of the (integrated) command framework * * @see Command * @see CommandRegistry @@ -75,7 +75,7 @@ namespace test { virtual void - run (Arg) + run (Arg) { CommandRegistry& registry = CommandRegistry::instance(); CHECK (®istry); @@ -124,9 +124,10 @@ namespace test { // now create a clone, registered under a different ID Command cmd2 = cmd1.storeDef(TEST_CMD2); - CHECK (cmd2 == cmd1); - cmd2.bind(54321); - CHECK (cmd2 != cmd1); + CHECK (cmd2 != cmd1); // note: while they are equivalent, they are not identical + Command cm2x = cmd2.bind(54321); + CHECK (cm2x != cmd1); + CHECK (cm2x == cmd2); // this created exactly one additional instance allocation: CHECK (1+cnt_inst == registry.instance_count()); @@ -143,6 +144,10 @@ namespace test { CHECK (cnt_defs == registry.index_size()); // removed from index CHECK (1+cnt_inst == registry.instance_count()); //...but still alive + CHECK (cmdX.isAnonymous()); + CHECK (cmd2.isAnonymous()); //......they got deached + CHECK (!cmd1.isAnonymous()); + // create a new registration.. registry.track(TEST_CMD2, cmd2); CHECK (registry.queryIndex(TEST_CMD2)); @@ -165,6 +170,7 @@ namespace test { cmdX.close(); CHECK (1+cnt_inst == registry.instance_count()); cmd2.close(); + cm2x.close(); CHECK (0+cnt_inst == registry.instance_count()); // ...as long as it's still referred } @@ -211,7 +217,6 @@ namespace test { CHECK (2+cnt_inst == registry.instance_count()); CHECK (!isSameObject (*pImpl, *clone)); - CHECK (*pImpl == *clone); CHECK (!pImpl->canExec()); typedef Types ArgType; @@ -220,12 +225,10 @@ namespace test { CHECK (pImpl->canExec()); CHECK (!clone->canExec()); // this proves the clone has indeed a separate identity - CHECK (*pImpl != *clone); // discard the first clone and overwrite with a new one clone = registry.createCloneImpl(*pImpl); CHECK (2+cnt_inst == registry.instance_count()); - CHECK (*pImpl == *clone); CHECK (clone->canExec()); clone.reset(); diff --git a/tests/core/steam/control/command-use1-test.cpp b/tests/core/steam/control/command-use1-test.cpp index c5e08e02a..17cd4253e 100644 --- a/tests/core/steam/control/command-use1-test.cpp +++ b/tests/core/steam/control/command-use1-test.cpp @@ -224,7 +224,7 @@ namespace test { CHECK (!c2.canUndo()); CHECK (c2.isAnonymous()); - CHECK (c1 == c2); + CHECK (c1 != c2); CHECK (!isSameObject(c1, c2)); CHECK (0 == command1::check_); @@ -234,7 +234,6 @@ namespace test { CHECK (randVal == command1::check_); CHECK ( c1.canUndo()); CHECK (!c2.canUndo()); - CHECK (c1 != c2); c2(); CHECK (randVal + randVal == command1::check_); @@ -271,7 +270,7 @@ namespace test { CHECK (c4.canUndo()); CHECK (not c4.isAnonymous()); CHECK ( c2.isAnonymous()); - CHECK (c4 == c2); + CHECK (c4 != c2); // note: it was stored as independent clone copy CHECK (c4 != c1); c4(); CHECK (c4 != c2); // now lives independently from the original diff --git a/tests/core/steam/control/memento-tie-test.cpp b/tests/core/steam/control/memento-tie-test.cpp index 7b5e73495..0bc5d96cb 100644 --- a/tests/core/steam/control/memento-tie-test.cpp +++ b/tests/core/steam/control/memento-tie-test.cpp @@ -87,7 +87,6 @@ namespace test { run (Arg) { checkStateCapturingMechanism(); - verifyComparisons(); } @@ -134,50 +133,6 @@ namespace test { bound_undo_func(3*rr); CHECK (testVal == -20 + 3*rr - (5+rr)); } - - - void - verifyComparisons() - { - function u1_fun; // deliberately unbound - function u2_fun = undo; - function< int(short)> c1_fun; - function< int(short)> c2_fun = capture; - - MemHolder m11 (u1_fun, c1_fun); - MemHolder m12 (u1_fun, c2_fun); - MemHolder m21 (u2_fun, c1_fun); - MemHolder m22 (u2_fun, c2_fun); - - CHECK (!m11 && !m12 && !m21 && !m22); - CHECK ( (m11 == m11)); - CHECK (!(m11 != m11)); - - CHECK (m11 != m12); - CHECK (m11 != m21); - CHECK (m11 != m22); - CHECK (m12 != m11); - CHECK (m12 != m21); - CHECK (m12 != m22); - CHECK (m21 != m11); - CHECK (m21 != m12); - CHECK (m21 != m22); - CHECK (m22 != m11); - CHECK (m22 != m12); - CHECK (m22 != m21); - - MemHolder m22x (m22); // clone copy - CHECK (!m22x); - CHECK (m22 == m22x); // same functions, no state --> equal - - testVal = 0; - m22x.tieCaptureFunc() (1 + (rand() % 9)); // produce a random memento value != 0 - CHECK (0 < m22x.getState()); - - CHECK (m22 != m22x); - m22.tieCaptureFunc() (m22x.getState()); // get the same value into the memento within m22 - CHECK (m22 == m22x); - } }; diff --git a/tests/core/steam/engine/dispatcher-interface-test.cpp b/tests/core/steam/engine/dispatcher-interface-test.cpp index e2998336e..62ebdc8c2 100644 --- a/tests/core/steam/engine/dispatcher-interface-test.cpp +++ b/tests/core/steam/engine/dispatcher-interface-test.cpp @@ -220,7 +220,7 @@ namespace test { #if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #880 TimeVar frameStart (refPoint); - InvocationInstanceID prevInvocationID(0); + InvocationInstanceID prevInvocationID(0); ///////////////////////////////////////////////////////TICKET #1138 : C++17 requires explicit ctor for initialisation of union Offset expectedTimeIncrement (1, FrameRate::PAL); for (uint i=0; i < plannedChunk.size(); ++i ) { diff --git a/tests/library/diff/tree-mutator-binding-test.cpp b/tests/library/diff/tree-mutator-binding-test.cpp index b3e224d4b..27b878a4b 100644 --- a/tests/library/diff/tree-mutator-binding-test.cpp +++ b/tests/library/diff/tree-mutator-binding-test.cpp @@ -977,6 +977,11 @@ namespace test{ +sizeof(void*) // the VTable for each layer of TreeMutator impl ) + 1 * sizeof(void*)); // plus one unused selector, implemented as pointer to the default impl +////////// +//////////NOTE: unexpected behaviour confirmed with GCC-8 +////////// +////////// However, the practice of verifying data size and layout assumptions +////////// is increasingly questionable, given that all modern compilers do data flow based optimisations. #endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1007 diff --git a/tests/library/format-string-test.cpp b/tests/library/format-string-test.cpp index 094a9de03..9f214007a 100644 --- a/tests/library/format-string-test.cpp +++ b/tests/library/format-string-test.cpp @@ -218,7 +218,8 @@ namespace test { struct Verbose : Silent { - Verbose(int i) : Silent(i) { } + using Silent::Silent; + virtual ~Verbose() { } virtual operator string() const @@ -230,7 +231,7 @@ namespace test { struct Explosive : Verbose { - Explosive(int i) : Verbose(i) { } + using Verbose::Verbose; operator string() const { @@ -291,7 +292,7 @@ namespace test { cout << _Fmt("__%d__") % "1234" << endl; cout << _Fmt("__%d__") % "0xff" << endl; - VERIFY_ERROR(FORMAT_SYNTAX, _Fmt("%broken")); + VERIFY_ERROR(FORMAT_SYNTAX, _Fmt("%madness")); } diff --git a/tests/library/functor-util-test.cpp b/tests/library/functor-util-test.cpp deleted file mode 100644 index da5a29f3c..000000000 --- a/tests/library/functor-util-test.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - FunctorUtil(Test) - verifying function object and signal utilities - - Copyright (C) Lumiera.org - 2009, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -* *****************************************************/ - -/** @file functor-util-test.cpp - ** unit test \ref FunctorUtil_test - */ - - - -#include "lib/test/run.hpp" -#include "lib/functor-util.hpp" - -#include -#include -#include - -using lib::HashVal; -using std::cout; -using std::function; -using boost::hash; // note: only boost::hash allows for easy defining of custom hash functions - - -namespace util { -namespace test { - - - namespace { - - void fun1 (int i) { cout << "fun1 (" << i << ")\n"; } - void fun2 (int i) { cout << "fun2 (" << i << ")\n"; } - - struct Dummy - { - void gummi (int i) { cout << "gummi (" << i << ")\n"; } - }; - } - - - - - - /*****************************************************************//** - * @test verify some aspects of the functor-util's behaviour. - * At times, this is just a scrapbook for new ideas.... - */ - class FunctorUtil_test : public Test - { - virtual void - run (Arg) - { - verifyBruteForceComparison(); - verifyHashThroughBackdoor(); - } - - typedef function Fvi; - typedef function Fiv; - - typedef function Fvv; - - - /** @test workaround for the missing functor comparison operator */ - void - verifyBruteForceComparison() - { - Fvi f0; - Fvi f1 (fun1); - Fvi f2 (fun2); - - CHECK (!rawComparison(f0, f1)); - CHECK (!rawComparison(f1, f2)); - CHECK (!rawComparison(f0, f2)); - - Fvi f22 (f2); - CHECK ( rawComparison(f2, f22)); - - f1 = f2; - CHECK ( rawComparison(f1, f2)); - - CHECK (!rawComparison(f0, Fvi())); // note: can't detect they are equivalent - CHECK (!rawComparison(f0, Fiv())); - - f1 = bind (fun2, _1); - CHECK (!rawComparison(f1, f2)); - - Dummy dum1, dum2; - Fvi fm1 = bind (&Dummy::gummi, dum1, _1); - Fvi fm2 = bind (&Dummy::gummi, dum2, _1); - Fvv fm3 = bind (&Dummy::gummi, dum1, 23); - Fvv fm4 = bind (&Dummy::gummi, dum1, 24); - Fvv fm5 = bind (&Dummy::gummi, dum2, 24); - Fvv fm6 = bind (&Dummy::gummi, dum2, 24); - - CHECK (!rawComparison(f1, fm1)); - - CHECK (!rawComparison(fm1, fm2)); - CHECK (!rawComparison(fm1, fm3)); - CHECK (!rawComparison(fm1, fm4)); - CHECK (!rawComparison(fm1, fm5)); - CHECK (!rawComparison(fm1, fm6)); - CHECK (!rawComparison(fm2, fm3)); - CHECK (!rawComparison(fm2, fm4)); - CHECK (!rawComparison(fm2, fm5)); - CHECK (!rawComparison(fm2, fm6)); - CHECK (!rawComparison(fm3, fm4)); - CHECK (!rawComparison(fm3, fm5)); - CHECK (!rawComparison(fm3, fm6)); - CHECK (!rawComparison(fm4, fm5)); // note: same argument but different functor instance - CHECK (!rawComparison(fm4, fm6)); - CHECK (!rawComparison(fm5, fm6)); // again: can't detect they are equivalent - } - - - /** @test workaround for missing standard hash - * calculation for functor objects. - * Workaround relying on boost - * implementation internals */ - void - verifyHashThroughBackdoor() - { - Fvi f0; - Fvi f1 (fun1); - Fvi f2 (fun2); - Fvi f22 (f2); - - hash calculateHash; - CHECK (calculateHash (f0)); - CHECK (calculateHash (f1)); - CHECK (calculateHash (f2)); - CHECK (calculateHash (f22)); - - HashVal h0 = calculateHash (f0); - HashVal h1 = calculateHash (f1); - HashVal h2 = calculateHash (f2); - HashVal h22 = calculateHash (f22); - - CHECK (h0 != h1); - CHECK (h0 != h2); - CHECK (h1 != h2); - - CHECK (h2 == h22); - - f1 = f2; - h1 = calculateHash (f1); - CHECK (h1 == h2); - CHECK (h1 != h0); - - CHECK (h0 != calculateHash (Fvi())); // note: equivalence not detected - - // checking functors based on member function(s) - Dummy dum1, dum2; - Fvi fm1 = bind (&Dummy::gummi, dum1, _1); - Fvi fm2 = bind (&Dummy::gummi, dum2, _1); - Fvv fm3 = bind (&Dummy::gummi, dum1, 23); - Fvv fm4 = bind (&Dummy::gummi, dum1, 24); - Fvv fm5 = bind (&Dummy::gummi, dum2, 24); - Fvv fm6 = bind (&Dummy::gummi, dum2, 24); - - HashVal hm1 = calculateHash (fm1); - HashVal hm2 = calculateHash (fm2); - - hash calculateHashVV; - HashVal hm3 = calculateHashVV (fm3); - HashVal hm4 = calculateHashVV (fm4); - HashVal hm5 = calculateHashVV (fm5); - HashVal hm6 = calculateHashVV (fm6); - - CHECK (h1 != hm1); - - CHECK (hm1 != hm2); - CHECK (hm1 != hm3); - CHECK (hm1 != hm4); - CHECK (hm1 != hm5); - CHECK (hm1 != hm6); - CHECK (hm2 != hm3); - CHECK (hm2 != hm4); - CHECK (hm2 != hm5); - CHECK (hm2 != hm6); - CHECK (hm3 != hm4); - CHECK (hm3 != hm5); - CHECK (hm3 != hm6); - CHECK (hm4 != hm5); - CHECK (hm4 != hm6); - CHECK (hm5 != hm6); // again: unable to detect the equivalence - } - }; - - - /** Register this test class... */ - LAUNCHER (FunctorUtil_test, "unit common"); - - - -}} // namespace util::test diff --git a/tests/library/maybe-value-test.cpp b/tests/library/maybe-value-test.cpp deleted file mode 100644 index a5630af9d..000000000 --- a/tests/library/maybe-value-test.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - MaybeValue(Test) - considerations for dealing with optional values - - Copyright (C) Lumiera.org - 2011, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -* *****************************************************/ - -/** @file maybe-value-test.cpp - ** unit test \ref MaybeValue_test - */ - - - - -#include "lib/test/run.hpp" -#include "lib/test/test-helper.hpp" -#include "lib/maybe.hpp" -#include "lib/util.hpp" - -//#include -//#include - - -namespace lib { -namespace test{ - - namespace error = lumiera::error; - -// using util::isSameObject; -// using std::rand; - using util::isnil; - using error::LUMIERA_ERROR_BOTTOM_VALUE; - - - namespace { // test data and helpers... - - - uint INVOCATION_CNT(0); - - /** helper for testing delayed evaluation */ - template - class Delayed - { - VAL v_; - - public: - Delayed (VAL val) : v_(val) { } - - VAL - operator() () const - { - ++INVOCATION_CNT; - return v_; - } - }; - - template - inline Delayed - yield (VAL val) - { - - } - } - - - - /***********************************************************************************//** - * @test Investigate various situations of using a Maybe value or option monad. - * @note this is a testbed for experiments for the time being 11/2011 - * - * @deprecated as of 2016 : the upcoming C++17 will provide an optional type!!!!! - * - * @see lib::Maybe - * @see null-value-test.cpp - * @see util::AccessCasted - */ - class MaybeValue_test : public Test - { - - void - run (Arg) - { - show_basicOperations(); - show_delayedAccess(); - } - - - void - show_basicOperations() - { -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #856 - Maybe one(1); - Maybe opt(5); - Maybe nil; - - CHECK (opt); CHECK (!isnil(opt)); - CHECK (!nil); CHECK ( isnil(nil)); - - // access the optional value - CHECK (1 == *one); - CHECK (5 == *opt); - - // can't access an bottom value - VERIFY_ERROR (BOTTOM_VALUE, *nil); - - // flatMap operation (apply a function) - CHECK (7 == *(opt >>= inc2)); - CHECK (9 == *(opt >>= inc2 >>= inc2)); - - // alternatives - CHECK (1 == *(one || opt)); - CHECK (5 == *(nil || opt)); - CHECK (1 == *(nil || one || opt)); - - CHECK (1 == one.get()); - CHECK (1 == one.getOrElse(9)); - CHECK (9 == nil.getOrElse(9)); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #856 - } - - - void - show_delayedAccess() - { - INVOCATION_CNT = 0; - - Maybe nil; - Maybe two(2); -#if false /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #856 - Maybe later(yield(5)); - CHECK (0 == INVOCATION_CNT); - - CHECK (2 == *(two || later)); - CHECK (0 == INVOCATION_CNT); - - CHECK (5 == *(nil || later)); - CHECK (1 == INVOCATION_CNT); - - later.get(); - CHECK (2 == INVOCATION_CNT); - - CHECK (2 == two.getOrElse(later)); - CHECK (2 == INVOCATION_CNT); - - CHECK (5 == nil.getOrElse(later)); - CHECK (3 == INVOCATION_CNT); - - // obviously, this also works just with a function - CHECK (7 == nil.getOrElse(yield(7))); - CHECK (4 == INVOCATION_CNT); - - // stripping the delayed evaluation - Maybe some = later; - CHECK (5 == INVOCATION_CNT); - CHECK (5 == some); - - CHECK (5 == INVOCATION_CNT); -#endif /////////////////////////////////////////////////////////////////////////////////////////////////////////////UNIMPLEMENTED :: TICKET #856 - } - }; - - - /** Register this test class... */ - LAUNCHER (MaybeValue_test, "unit common"); - - -}} // namespace lib::test diff --git a/tests/library/meta/function-erasure-test.cpp b/tests/library/meta/function-erasure-test.cpp index 9cda013e6..60dfeb7f5 100644 --- a/tests/library/meta/function-erasure-test.cpp +++ b/tests/library/meta/function-erasure-test.cpp @@ -88,27 +88,6 @@ namespace test { check_FunctPtrHolder(Efp(testFunc),Efp(&testFunc), Efp(returnIt)); check_VoidPtrHolder(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt)); - check_Comparisons (Efun(testFunc), Efun(bindFunc)); - check_Comparisons (Efun(testFunc), Efun(pAplFunc)); - check_Comparisons (Efun(testFunc), Efun(membFunc)); - check_Comparisons (Efun(testFunc), Efun(getterFunc)); - check_Comparisons (Efun(bindFunc), Efun(pAplFunc)); - check_Comparisons (Efun(bindFunc), Efun(membFunc)); - check_Comparisons (Efun(bindFunc), Efun(getterFunc)); - check_Comparisons (Efun(pAplFunc), Efun(membFunc)); - check_Comparisons (Efun(pAplFunc), Efun(getterFunc)); - check_Comparisons (Efun(membFunc), Efun(getterFunc)); - - check_Comparisons (Efp(testFunc), Efp(returnIt)); - check_Comparisons (Evoid(testFunc), Evoid(returnIt)); - - CHECK ( detect_Clone (Efun(testFunc))); - CHECK (!detect_Clone (Efun(bindFunc))); //note equality not detected when cloning a bind term - CHECK (!detect_Clone (Efun(pAplFunc))); //similarly - CHECK (!detect_Clone (Efun(membFunc))); //analogous for bound member function - CHECK ( detect_Clone (Efp(testFunc) )); - CHECK ( detect_Clone (Evoid(testFunc))); - detect_unboundFunctor(Efun(testFunc), Efun(getterFunc), Efun(membFunc)); detect_unboundFunctor(Efp(testFunc),Efp(&testFunc), Efp(returnIt)); detect_unboundFunctor(Evoid(testFunc),Evoid(&testFunc),Evoid(returnIt)); @@ -194,11 +173,6 @@ namespace test { CHECK (_sum_ == 10+'a'+20+'b'+30+'c'); CHECK (_sum_ == (f3.getFun()) () ); - -#if false ////////////////////////////////////////////////////////TODO: restore throwing ASSERT - VERIFY_ERROR (ASSERTION, f1.getFun() ); -#endif//////////////////////////////////////////////////////////// - } @@ -231,27 +205,6 @@ namespace test { } // likely to result in heap corruption or SEGV - template - void - check_Comparisons (HOL h1, HOL h2) - { - CHECK (h1 == h1); CHECK (!(h1 != h1)); - CHECK (h2 == h2); CHECK (!(h2 != h2)); - - CHECK (h1 != h2); - CHECK (h2 != h1); - } - - - template - bool - detect_Clone (HOL const& h1) - { - HOL clone (h1); - return (clone == h1); - } - - template void detect_unboundFunctor (HOL h1, HOL h2, HOL h3) diff --git a/tests/vault/thread-local-test.cpp b/tests/vault/thread-local-test.cpp deleted file mode 100644 index 16c960cc3..000000000 --- a/tests/vault/thread-local-test.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - ThreadLocal(Test) - verify wrapper for using thread-local data - - Copyright (C) Lumiera.org - 2011, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -* *****************************************************/ - -/** @file thread-local-test.cpp - ** unit test \ref ThreadLocal_test - */ - - -#include "lib/test/run.hpp" - -#include "vault/thread-wrapper.hpp" -#include "lib/thread-local.hpp" - -#include - -using test::Test; -using vault::ThreadJoinable; -using std::rand; - - -namespace lib { -namespace test{ - - namespace { // private test setup... - - const uint NUM_THREADS = 50; - const uint MAX_RAND = 5*1000*1000; - - - /** Subject of the test */ - ThreadLocalPtr privateValue; - - - - - struct TestThread - : ThreadJoinable - { - TestThread() - : ThreadJoinable("test Thread-local storage" - ,verifyThreadLocal) - { } - - - /** the actual test operation running in a separate thread */ - static void - verifyThreadLocal() - { - uint secret (1 + rand() % MAX_RAND); - privateValue.set (&secret); - - usleep (secret); // sleep for a random period - - if (secret != *privateValue) - throw error::Fatal ("thread-local value access broken"); - } - }; - - } // (End) test setup.... - - - - - - - - - - - /**********************************************************************//** - * @test use a wrapper to simplify handling of thread-local data. - * Create some threads, each referring to another piece of data - * through the "same" wrapper instance. - * - * @see vault::Thread - * @see lib::ThreadLocal - */ - class ThreadLocal_test : public Test - { - - virtual void - run (Arg) - { - TestThread testcase[NUM_THREADS] SIDEEFFECT; - - for (uint i=0; i < NUM_THREADS; ++i) - CHECK (testcase[i].join().isValid() ); - } - }; - - - - /** Register this test class... */ - LAUNCHER (ThreadLocal_test, "function common"); - - - -}} // namespace vault::test diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 568a7c44a..da38d2c27 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -21444,8 +21444,7 @@ (genauer gesagt, die Basisklasse Gtk::Object macht das)

- - + @@ -21973,8 +21972,7 @@ weil dieses nämlich keine Koordinaten bekommt, und daher nicht weiß, in welchem Canvas das zu entfernde Widget steckt

- - + @@ -51761,21 +51759,52 @@ - + + - - - + + + + + + + + + + + + + + + + + - - + + + + + + + + + - - + + + + + + + + + + + @@ -51807,23 +51836,37 @@ - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + @@ -51879,13 +51922,16 @@ - + + + + + + - + - - - + @@ -51897,7 +51943,7 @@ - + @@ -51909,7 +51955,7 @@ - + @@ -51935,7 +51981,7 @@ - + @@ -51947,12 +51993,12 @@ - - - + + + - + @@ -51964,10 +52010,10 @@ - - - - + + + + @@ -51980,7 +52026,7 @@ - + @@ -51994,7 +52040,7 @@

- + @@ -52006,7 +52052,7 @@ - + @@ -52021,7 +52067,7 @@ - + @@ -52033,9 +52079,9 @@ - - - + + + @@ -52047,7 +52093,7 @@ - + @@ -52062,7 +52108,7 @@ - + @@ -52077,7 +52123,7 @@ - + @@ -52098,8 +52144,9 @@ - - + + + @@ -52115,10 +52162,10 @@ - + - + @@ -52137,11 +52184,11 @@ - - + + - + @@ -52153,9 +52200,9 @@ - - - + + + @@ -52167,9 +52214,9 @@ - + - + @@ -52182,7 +52229,7 @@ - + @@ -52195,7 +52242,7 @@ - + @@ -52231,29 +52278,33 @@ - + + - - - + + + - + + + - + + - + @@ -52272,7 +52323,7 @@ - + @@ -52285,11 +52336,87 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ früher war das so eine typische "nörgel"-Warnung, die man unter den Teppich kehren konnte: 'ey, der Compiler bekommt es ja trotzdem richtig hin. +

+ +
+ +
+
+
+
+ + + + + + + + + +
    +
  • + sinnvollen Zustand erreichen: zumindest das neue GUI sollte wieder starten +
  • +
  • + dann Paket aktualisieren und neu bauen +
  • +
+ +
+ +
+ + + +
+ + + + + + + + + + + @@ -52302,7 +52429,7 @@ - + @@ -52344,11 +52471,11 @@ - + - + @@ -52401,7 +52528,7 @@ - + @@ -52426,7 +52553,7 @@ - + @@ -52450,7 +52577,7 @@ - + @@ -52492,7 +52619,7 @@ - + @@ -52507,7 +52634,7 @@ - + @@ -52521,13 +52648,13 @@ - - - - + + + + - - + + @@ -52554,17 +52681,563 @@ - - + + + + + + + + + + +

+ Grund ist die Umstellung auf inline-Storage +

+ +
+ +
+ + + + + + +

+ wäre theoretisch jetzt möglich, +

+

+ da wir nun eine vollwertige String-Tabelle haben +

+ +
+
- + + + + + + + + + + + + + + + + +

+ waren nur minimale Anpassungen +

+ +
+ +
+ + + + - - - + + + + + + + + + + + + + + + + + + + +

+ das Problem wurde vom GCC beim Bauen des alten Lumiera-Paketes angemahnt; tatsächlich aber hatte ich das Problem inzwischen längst schon anderweitig bemerkt und an der Wurzel gelöst, anstatt nur Symptome zu behandeln +

+ +
+ +
+
+ + + + + + + + +

+ als "workaround" hatte ich boost::rational<long> genommen +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ und wir brauchen die definitiv zum sinnvollen Rechenen mit Zeiten auf micro-Scala +

+ +
+ + + + + +

+ Der kritsche Fall ist nämlich, wenn wir mit FSecs anfangen, und dann irgendwo in der Rechnung mal Time::SCALE multiplizieren, um auf die µ-Skala zu wechseln. Am Ende der Rechnung würde dann typischerweise ein rational_cast stehen. Damit das funktioniert, muß vor allem der Zähler des Bruches die volle Zeitskala unterstützen. Daher sind 64bit zwingend +

+ +
+ + +
+
+ + + + + + + + +

+ weil 64bit -> 32bit eine narrowing conversion ist, die zumindest eine Warnung erzeugt +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ src/lib/itertools.hpp:805 +

+

+ error: no type named 'Ret' in 'struct lib::meta::_Fun<std::__cxx11::basic_string<char> (*)(const std::__cxx11::basic_string<char>&) noexcept, void>' +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ die überladene const-Variante ist der Grund +

+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ Frage: wollen wir auf noexcept einschränken? +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + +
    +
  • + als schneller Fix implementiert +
  • +
  • + und tatsächlich nur einmal, für einen Test verwendet +
  • +
  • + eigentlich wird damit das Problem "unter den Teppich gekehrt" +
  • +
+ +
+ +
+
+ + + + + + + +

+ "sinnvoll" heißt +

+
    +
  • + stabil +
  • +
  • + lesbar +
  • +
+ +
+ +
+
+ + + + + + + + + + + + + + +

+ warum...? +

+

+ ..vermutlich, weil ich ab einem gewissen Punkt damit angefangen habe, auch die Lumiera-Iteratoren als "foreach-iterierbar" zu dekorieren (indem sie freie begin(iter) und end(iter)-Funktionen bieten). +

+ +
+ +
+
+ + + +
+ + + + + + + + + +

+ es sollte genau die Eigenschaften abdecken, die wir tatsächlich brauchen +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ mit const und volatile... +

+ +
+ +
+
+
+
+
+
+ + + + + + +
+ + + @@ -52577,7 +53250,6 @@ - @@ -52588,11 +53260,10 @@ hier nach offensichtlich obsoleter Info checken

- WICHTIG: keine vorgreifende Infor publizieren!!!!! + WICHTIG: keine vorgreifende Infos publizieren!!!!!

-
@@ -52611,14 +53282,11 @@

- - - - + @@ -52632,7 +53300,6 @@ - @@ -52659,18 +53326,11 @@ - - - + + + - - - - - - - - + @@ -52685,7 +53345,6 @@ - @@ -52697,7 +53356,7 @@ - + @@ -52712,26 +53371,16 @@ - - - - - - - - + + - - - - - - + + @@ -52751,7 +53400,7 @@ - + @@ -52762,7 +53411,7 @@

- + @@ -52782,9 +53431,8 @@ - - - + + @@ -52797,7 +53445,7 @@ - + @@ -52812,7 +53460,7 @@ - + @@ -52843,8 +53491,8 @@ - - + + @@ -52889,7 +53537,7 @@
- + @@ -52914,8 +53562,8 @@ - - + + @@ -52928,30 +53576,23 @@

-
- - - - + + + + - - - - - - - - + - - + + + - + @@ -52988,10 +53629,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + @@ -53005,7 +53680,7 @@ - + @@ -53021,38 +53696,6 @@ - - - - - - - - - - -

- Probleme mit der Compile-Reihenfolge  #973 -

- -
- -
-
- - - - - - - - - - - - - -
@@ -53128,7 +53771,7 @@
- + @@ -53144,13 +53787,40 @@ + + + + + + + + +

+ Probleme mit der Compile-Reihenfolge  #973 +

+ +
+
- - - + + + + + + + + + + + + + + + + - + @@ -53199,7 +53869,7 @@ - + @@ -53213,7 +53883,7 @@ - + @@ -53250,7 +53920,7 @@ - + @@ -53272,7 +53942,7 @@ - + @@ -53291,6 +53961,238 @@ + + + + + + + + + +

+ angeregt durch Gabriel; +

+

+ er wollte "versuchen, Lumiera zu bauen" +

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+ wann sind Funktoren äquivalent ?? +

+ +
+ + + + + +

+ mathematisch gilt: +

+

+ sie sind gleich, wenn sie für alle gleichen Argumente das gleiche Resultat liefern. +

+

+ +

+

+ sei die Dose offen... +

+ +
+
+ + + + + + + + + +

+ in tr1::functional war ein equality-Operator spezifiziert +

+

+ boost::function hat sich geweigert diesen zu implementieren, +

+

+ weil es keine vernünftige und konsistente Implementierung gibt. +

+

+ +

+

+ Für den C++11 - Standard hat man dann einen Kompromiß geschlossen, +

+

+ demnach der Vergleich mit einem NULLPTR sinnvoll (und implementierbar) ist, +

+

+ aber ansonsten alle validen definierten Funktionen untereinander verschieden sind. +

+ +
+ +
+ + + + + +
+
+ + + + + + + + + + + + + + + + +

+ sonst auf Äquivalenz getestet +

+ +
+
+
+ + + + + + +

+ und genau das Letztere ist nicht garantiert korrekt implementierbar +

+ +
+
+
+ + + + + + + + + + + + + + + +

+ Selbst verschiedene Closures haben selbst die noch eine eindeutige Identität +

+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +

+ d.h. wir brauchen keine Äquivalenz? +

+ +
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + +
+
+
+
+
+ + + @@ -53310,7 +54212,7 @@ - + @@ -53339,10 +54241,10 @@ - + - + @@ -53366,7 +54268,7 @@ - + @@ -53401,7 +54303,7 @@ - + @@ -53413,13 +54315,13 @@ - + - + @@ -53450,7 +54352,7 @@ - +