From 4b29885d51e48685108578c243a2b8391cb01f59 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 22 Jun 2019 19:14:54 +0200 Subject: [PATCH 01/16] Docker: setup a Lumiera build environment in a Debian/Ubuntu container some scripting to help creating a clean build environment for testing and bugfixes * build_lumiera-build-dependencies.sh All necessary steps to prepare a pristine Debian/Ubuntu/xx distro for building Lumiera from source. + install the GPG pub key to trust + install a Lumiera DEP Repository to get the sources from + install build-essential + prepare, build and install NoBug + prepare, build and install libGDLmm + install the Lumiera build-dependencies from the DEB package At that point, you should be able to start the build just with `scons` * docker_open-lumiera-buildenv.sh Additional bash magic to launch a docker container and inject the build_lumiera-build-dependencies.sh script into an interactive shell --- admin/README.deb.lumiera.org.PUB.gpg | 5 ++ admin/build_lumiera-build-dependencies.sh | 61 ++++++++++++++++++++++ admin/deb.lumiera.org.PUB.gpg | Bin 0 -> 6927 bytes admin/docker_open-lumiera-buildenv.sh | 44 ++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 admin/README.deb.lumiera.org.PUB.gpg create mode 100755 admin/build_lumiera-build-dependencies.sh create mode 100644 admin/deb.lumiera.org.PUB.gpg create mode 100755 admin/docker_open-lumiera-buildenv.sh 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 0000000000000000000000000000000000000000..6403dc3b65d41cd281de173ec2ec5717839012c1 GIT binary patch literal 6927 zcmb`Mbx<7J_NZqD26rdHEqJitB)9|#F2QAR7?=RT37SEJ6M_xyK6r4~-~@*t!8O4N zFX#O3edoM-uTI^1b^EXG{$uy9y}xg*wO6MCb5O-EktKwvfU~wMmYo3LfW_#hlLApF zJlM6vT;F?3-q!y(73wE7=zCz;oKKtjqH3|Wf z!*M`VP;3-cCdin{x3#Uz#Mp8sbtW#;#$UsI&n0*%l4zx z*Pol+`*t^p!WXT*Rsy~=Qblee(#x8Lj%_CzCS0G;dq@jhD%NkaJkU39U9FOyBQTZn z8Yaz7mbues?-GNuY$uFHgKb4l=YwGALQvy4iX`-?%|+%<07c{v`Pp zV!>?%c@CFHB_;#`(7+&RB4Qc<7ACkBLE_vBA#|o+6w-O)1f?TjA|;U zjmi^{DJYg9kq!JV49!;W93`tYdaJQ|3b#ik_&p8-h!O~*0fNZifkCf#@qVFUV`8AA zfWV|!m>Ae#G87;P03bq#D5xs{fIv(FNWBAk_DW)nfG{A-y6EMh#1Y9*z&;NO36eVi znJ{z?Kx};&+;?`3c&S5RqU86=n=yT^b~+qHg-Y;yq~DW%Wo#z*$E4L+eeVNupkLU- z@gIx|Om#K*uzneZ5~e6iqL3f!Z^~_V@B)lD@)}WJS)V7%CDhmD%X`w6RQT8!U3QxL z2;dNAV(t#-gsJyDf)kOS(DI?+u~1&SZ3hERU7$ek`X{dHLSl>e7pu&LvIX_=X{iyO7iH^$^Ykvzcbs-3!|N5sE>amX8TAGb*KhiqT%J+M!t+$8%wi#( zdJlb8jkYr_!*SeKBv(qYy|~qs8FFZ7<6SST{6zXFZLmBD2U2`;=LPsJ54i|cPb_Ak z+HYgpwPikd^TX%7yz&flh3WudRepgwfi~|6)Pj!q#nf`Ab*kbOJoWKsPo!Q0 z32eVl&Ukmg>Wy*37jj0&>wSnLOoj=0NkO9{$03p&PF-PHwdHaOY({Y-5tn&#NG3O1 zh#~~$WbW)tCvN*cH zy)WE$ow>)rO^|py0Aj|J^D;3}K;g^w%f4nK&6LvnFW`RwwTy@W&{*OeXWO-8WZg07 zQo%@#Z4tkhf71&fxn|!0Ht?Y}qlgqzDx< zXic-TbyeOShkAYUNErgx#rrfEBHwBAk8w&htGBf+;Fo^CInYLVM-(5r2=@VYrdk`A{{&(%oZ z7xak8v2jZU;T84SN5n!HOWtt5#9T)|Hg-nOnr06hqVQOb+g|8eQNc4HTJ$!yK@q9)@H@znymgFH4+UuG;N{h-6K=12!CM> z&O1jp(H}oB1}yLrPwBC=v%zr{PL3}|5@gU@U0lW|fVTGmxYdaj0JKUL9B(rB;~FoU z(Yp{Rj&QAWTc+y_`Pt2n?1m$xl~v6rL?{$k;)nW(Mdn+*iOy7=UukU^vf%vtBg!Mt z)QekcRPwcmXYIxB#jPJD7b+~Cv8`n9QceuqzoOG1F?+^FoBP(;Rd<89X|lomWef7@ zPqf#>dVR1oO%bxl^0&UInrl1?suNsB_+HjLU5v2JYdqwu1{|512@S%`` zP*BJ~{|cmkgtvd=mv08hWX63Lg=$V-6r?H2L%>&`$qZ9C24tC^s*QZ>IN#{ZydkqY zL)7yqkqGrMh&Go`qQ>}~Yei8QqE(f8&i zL|YyDW9_4tMQ7&Wg!GcPa@K(=S@xW)%k(Ox;@Hz`b3`ly zi70UrC$-->?`yR*n%HXwPLvpMiNR!{!h(wRgK1%$X?M+*Ad9vY$6xk5LKHRUm~I~R zt9i?_$J0j{kM2^&jtBAWoPwPdo4+jEJ`lz*oypK6G!P1Tig-CY*qn?)JZ*wLaz&A4l^1X#W(T@dizshp5ARQ?)n6u%6swe;ujzG=5mwCaV!Csup7nRNk3qh! zIa`GXfaAa6I1rYT4%$$ES3=H-#ebt*3oAeZd%6b)&>TW&aP?u+=!Y_3Q|K8*%`f_I z4TYITubD3p`Oz@qI-|Aob*)vA6Rpn%iM^OdGim{gT)f%~oS))t#Vo0+uSF&)`FS15 zqDuf!S={Gbi$2k%sz7U0MMu-(me6x%cTY%1LEi%r-~ z{7}SK@TDpXA#WwQSNew2TqEy&MSvWVvWW)`;4zrE4pF1uHu;ersdcGyDfDC0uIY*Bc9!wujpjeA6GggtEGO_zbI;B=Q^0p zck%ViVlIvXVcFG~<+nHEW|@gNeh%&6T#1&AaDG-~ZEF)Qs04iBCDd(SG%sYxJJ<_1 zTg_!C#ESP1o-8sg9&!IBMqkwM?N!KBQP7PL_7&k(-{z@`0==wjcHT&fkR*g!jXkFbKsZ4Jb%WeFnUiqU7PsJ+Pb|)ppmFl@}WoQSXjSc%9lvOUgzvK@Lxr8S~hLCyUbXk2C5J0m0 zWySwEKqqbmvG^|~h+lSqG%)s_s*x<_GM>;1g5MLpwC*%`=6Bv2|H)t1R9jqYO@bQY z18Yu{184t(3V|{NfYj-3=&VK**}JUHDh;m^_IZ_*gt@|B){eX|iDoWNO$qYwL08FA zwgUQ6WIZhCdS1aUsyz09(la*!T?6`sa*#4}I(;S4DLU0Yq5y}2C;uv6SAxTe(Xspx z@Ke5xVfP24K%(_1UVaH%bL_GQANu(blkDCT%g~`mRb= zc6+CfY~RYy7&pkPSShnMJ*Ydi2eWq^Zshw$#S!B^I2p#&SroK+EXlwsWmjXRjY25z z36YeP?~+o*Kg1F;MRBO?(jb$cTs)&#Kr}@vq94aU;>pw^1do^^#4)g*)EdT5+eg0G z2$#K&d|Zv_6%#s4uOaY1NPQcoPqlXRLzJSQ^wD*yToyxyu*s_u6Ey)7w_mD0$&K5L z7F^DY0_;Bi-juL3u0cgfizeFH51s5bY3{tbMPs~o@>o*Y5D(g|OqARxa&hOI zH|?V>mFJWNiQFcvm%GoHQH#zo%^sQ))&ky$Zi&`zpJdLKr>za`7L|y)_dvI@uRE)( zkG8}|Y-eb<&xWs=KMZ_(5C2xM%jZ{u`9@+%bxrfhnA6v}H&c&o2&=Pkb)la~_ZrUW zdTB5ck9XB}4)e!iotF zQ4T&^;um>709`TUc6m2bxy87-n${aI8R7S2zBl|ik^HkL0BSqg=dcuAvuxZjuj>8R zmRg^0Ko4A(RWX#pBu+1J`?S#Mz69FOh=yWmAD$O$OCqT>)B->E?cign_K;O|lHY~2 zDInf#GfK%ZB4U-A3Gd|-m%P|%f>$Onky^46>%=EEXzQU{SZJrNeXPufBm9C5>8}}w zV+;mAdejD3dpCY``_b(kjh`yu=Amvatt6B!KVS= za&*N}*cj{yj(bxzaqz7S4pdB8x2&CnG_c}R`i-B5S1q8yXImCj0(p+;BG>h9Rid6Z zwds?p^V*54bt_OOdqUFJuKkc@3aRJg5d?8}LCV=S^QOMWo;E$BQ=y~vN+{eURWYp` zX{+05N?j?H-n5NamY#R&7EtVo=g}lhO9jgLo(k)8xZ2a~Yoz-4>l(0*fC80%bJRQU z<4qj=oFb+q#(IP3M)F>e>#qsF3Nk z8v5w6y*S%Fe~xOY4fCW@lQ;nq3V>xn@ob~6azv#6A??rcRsFwfv10$9X)&7*$Yc{w zdJ~ipLHK?|6^MM`G18v=>gmR0lCw*GK%7vYjvD?imCV|lNPr2dx#bmA^BoBvX3 z2r33-vOd&fcF3bV^DX9sRMoz8e`o6WQX&5j4h*E? z-%}mdeR)XIFf3_L=;@QIxf1ESZ(*iM1Fc=J(n^#>f4$u$IViI{6OyO&mt2tkSa*l# zvC11HB6d%lU#{@u0hNTJWjnB<*9&f4=08j zmkiw{QvsVF(jT<&VV@PyKgEI^4Uoi*VHyR7jXf?G@k)@pmceUCww_HG84+I*g151+3Y zjegvm`ugT57~4tO|0{puD$rM9!<AHdc;><*%B} z_Ve%hSomF8w>K|)F5wy2Tb&?fy{u|hKC((r6TtZ{h7k*c@6Y!bPl{;bE0ea?^=h+^ zY0PVJ%M$OLhGZH2Nm5N}sqOYV(M8rJK7AVW@2vhPFL<{(%buEK(m%_VXGOBqoI<zAvwdZ&%SHdK``F+?F335X);yd#-}@;Km|Np1c|`2^Q`0zFm1kYU zX_6S(#e$1;stc4p<;G)n+FlJ5qRlU#!8zZxwbH^s{XsJA?-XUDouDCH8~oi8S+v1K9=Ya|B()FEVMCbFzFyZvgugh%2O++2=-IiTwE ziTyuwU{MQzSc?Wn5q~IPI^feA`YHIbv_y2P9e~Jw@~%%XmJqe95)?XeVzANnwPU&o zg!^ZUn*alFA+6Vd5r9Ds%W0l1mOcmXTx$`EysAHSZc-MeTL2d7=927wkkmOJNADY! zDNZcERIv(Ey21%=h3t|~XHThL{WLIL^3Z%GArZYemb$JNZ!mh_SmE}n_s-*UaIXT7 z`IzsZ^#kd3%YB?lKd@xVFf$sF4-=h!bkZ&l(C66t0l(K*Q(7FQLuPEop$j_jI|}2< zQRDlpWwrtaRVjaAgKcmgdqNlWv_| zK5Q`n2!#G%3A8TBy(nkru^s*u?$RLZj) zV&!2uIP@bjB7CFq8YESUl^nJ7x*p}|Jxf{VqAx;6uIFa=EJ5!qDM>CZx$f?>~v zOe9E0MTvJ1dLB9-X_m#Uc`gxThuQhGLRs1Dr^yFFXN!y=RLX$p6o1;0#+c>zNm?{H zKNc-gPw?*bd%imfSFhaCTTg`0Lg!E^#V)%rzg{ z=+BDxf!m?7{_b$IfkCQ1`Q8lFC@`qIo1HU+&eGQ0*#<%fwWfnOTf)3t-0YyvbPf=& zzgHy`J%DsfRe8Zdjw^lad{b+0B<~<~f2S@WlaCh*-}vbGq02imAe-KmIUp>i5U!0% z@%vLaV9+1`Sip~Q0KYGyzuG|mZlL!;0Ekay65sFrOU5*ViRnt_!-Tx>EVlrNg`C?g zHXZM;>p0R_(5G{|Xda#zO+Z{!Ri8XJAO@hf2-cAow>rfLd3v)j&k{opE}gC*_?}TI z89bX3i}I7|;F^V}APA*gcQ{?pCxDbuGKegx5S?j%JBPDP0B&y<)FHSxY_SZ9u1O7%+Lc+iL`*LV=NR5PNV>_WGb z17|&i>xDU0-YV_La3{99m%2AcIH)G_GnSDkMrsarU>S(EA_4lePc(J6sgvuV36fE4 z?-nYwJS@<++k>W0JgfujJ#ojNO#!dTa!Q)Hj@`}?#gaP?k^A~vGZyLeC^46Gl*YkP zi@IZUn?gekt5R1c(^~!Z@cTeXp)3F)5CDWL{kh7Re{5*p@9Glg?;B=#2|%|n|#HjfRYVkU=rRJZGOln|6i>s{WAan literal 0 HcmV?d00001 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) < Date: Sat, 22 Jun 2019 15:15:56 +0200 Subject: [PATCH 02/16] Boost-1.65: resolve ambiguity in timevalue comparison seemingly, the newer boost libraries added an internal type rational::bool_type together with an overload for the equality comparison operator. Unfortunately this now renders a comparison ambiguous with the constant zero (i.e. int{0}) because in our use case we employ rational. Workaround is to compare explicitly to a zero of the underlying integer type. --- src/lib/time/timevalue.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/time/timevalue.hpp b/src/lib/time/timevalue.hpp index a93691ad0..277aa553c 100644 --- a/src/lib/time/timevalue.hpp +++ b/src/lib/time/timevalue.hpp @@ -583,7 +583,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; From aad71a496a141d226f1295be709e9796fdc2439e Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 22 Jun 2019 21:26:18 +0200 Subject: [PATCH 03/16] Boost-1.65: fix another integer ambiguity problem with boost::rational the "improved" boost::rational can no longer compute 1/x quite brilliant well... the reason is again signed vs unsigned int. FrameRate is based on unsigned int (since a negative frame rate makes no sense). --- src/lib/time/timevalue.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib/time/timevalue.hpp b/src/lib/time/timevalue.hpp index 277aa553c..0755e4969 100644 --- a/src/lib/time/timevalue.hpp +++ b/src/lib/time/timevalue.hpp @@ -572,6 +572,13 @@ namespace time { operator std::string() const; }; + /** convenient conversion to duration in fractional seconds */ + inline FSecs + operator/ (int n, FrameRate rate) + { + return n / boost::rational_cast (rate); + } + From d57770ca89981f4df61755dfb4f6bc268b3ed483 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 23 Jun 2019 17:35:21 +0200 Subject: [PATCH 04/16] Commands: disable equivalence-test on command equality This was prompted by a test failing under Boost-1.65 (--> see #294) When reviewed now, the whole idea of testing Steam-Layer Commands for equivalence feels a bit sketchy. Just the comparison for the command ''identity'' alone seems sufficient, i.e. the test if a command-ID is associated with the same backend-handle and thus the same functor binding. --- src/steam/control/command.hpp | 12 +- .../steam/control/command-registry-test.cpp | 16 +- .../core/steam/control/command-use1-test.cpp | 5 +- wiki/thinkPad.ichthyo.mm | 417 ++++++++++++++++-- 4 files changed, 401 insertions(+), 49 deletions(-) diff --git a/src/steam/control/command.hpp b/src/steam/control/command.hpp index daa298081..7b1191976 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) * @@ -312,9 +312,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 +326,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/tests/core/steam/control/command-registry-test.cpp b/tests/core/steam/control/command-registry-test.cpp index 8137fe36a..0e9e118fa 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 } 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/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 9033a0c88..a1aeb3065 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -20338,8 +20338,7 @@ innerhalb eines PolymorphicValue.

- - + @@ -20357,8 +20356,7 @@ stets selbst erzeugen und daher auf das korrekte Literal Verlaß ist)

- -
+
@@ -44386,21 +44384,52 @@ - + + - - - + + + + + + + + + + + + + + + + + - - + + + + + + + + + - - + + + + + + + + + + + @@ -44432,23 +44461,37 @@ - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + @@ -44474,7 +44517,7 @@ - + @@ -44528,7 +44571,7 @@ - + @@ -44691,8 +44734,9 @@ - - + + + @@ -44824,7 +44868,8 @@ - + + @@ -44841,6 +44886,9 @@ + + + @@ -45119,8 +45167,8 @@ - - + + @@ -45147,15 +45195,79 @@ - + + + + + + + + + + +

+ 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 +

+ + +
+ +
+ + + + +
- + @@ -45541,10 +45653,12 @@ - + + + - + @@ -45581,6 +45695,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -45648,10 +45795,10 @@ - + - + @@ -45792,6 +45939,208 @@ + + + + + + + + + + +

+ 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 +

+ + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
From 94edb5de866dbf0cbb79a388f666e0220c7a09cd Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 23 Jun 2019 18:57:21 +0200 Subject: [PATCH 05/16] BufferMetadata: likewise abandon use of function comparison for buffer handlers The existing implementation created a Buffer-Type based on various traits, including the constructor and destructor functions for the buffer content. However, this necessitates calculating the hash_value of a std::function, which (see #294) is generally not possible to implement. So with this changeset we now store an additional identity hash value right into the TypeHandler, based on the target type placed into the buffer --- src/lib/functor-util.hpp | 12 +- src/steam/engine/type-handler.hpp | 37 +++-- tests/library/functor-util-test.cpp | 238 ++++++++++++++-------------- wiki/thinkPad.ichthyo.mm | 36 +++++ 4 files changed, 185 insertions(+), 138 deletions(-) diff --git a/src/lib/functor-util.hpp b/src/lib/functor-util.hpp index 4512d54d5..92ed46633 100644 --- a/src/lib/functor-util.hpp +++ b/src/lib/functor-util.hpp @@ -178,12 +178,12 @@ namespace std { * @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); - } +// template +// inline lib::HashVal +// hash_value (function const& fun) +// { +// return util::rawHashValue (fun); +// } } diff --git a/src/steam/engine/type-handler.hpp b/src/steam/engine/type-handler.hpp index 47359afd7..cf49bcd9e 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). @@ -84,6 +84,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 +107,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 +122,13 @@ namespace engine { DoInBuffer createAttached; DoInBuffer destroyAttached; + HashVal identity; /** build an invalid NIL TypeHandler */ TypeHandler() : createAttached() , destroyAttached() + , identity{0} { } /** build a TypeHandler @@ -124,6 +142,7 @@ namespace engine { TypeHandler(CTOR ctor, DTOR dtor) : createAttached (ctor) , destroyAttached (dtor) + , identity{deriveCombinedTypeIdenity()} { } /** builder function defining a TypeHandler @@ -154,22 +173,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/library/functor-util-test.cpp b/tests/library/functor-util-test.cpp index da5a29f3c..ad1e11c7b 100644 --- a/tests/library/functor-util-test.cpp +++ b/tests/library/functor-util-test.cpp @@ -67,8 +67,8 @@ namespace test { virtual void run (Arg) { - verifyBruteForceComparison(); - verifyHashThroughBackdoor(); +// verifyBruteForceComparison(); +// verifyHashThroughBackdoor(); } typedef function Fvi; @@ -78,129 +78,129 @@ namespace test { /** @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 - } +// 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 - } +// 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 +// } }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index a1aeb3065..cdba0726f 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -46127,6 +46127,42 @@ + + + + + + + + + + + +

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

+ + +
+
+ + + + + + + + + + + + + + + + + +
From ab90d9c71d1d85417b3c2dec6939de019fc8c0f4 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 23 Jun 2019 19:43:47 +0200 Subject: [PATCH 06/16] Functions-Commands: discard the ability to compare functors for equivalence (closes #294) evil hack R.I.P --- doc/technical/code/darkCorners.txt | 40 ---- src/common/guifacade.cpp | 1 - src/lib/functor-util.hpp | 190 ---------------- src/lib/meta/function-erasure.hpp | 25 --- src/lib/meta/maybe-compare.hpp | 18 +- src/steam/control/command-closure.hpp | 1 - src/steam/control/command-impl.hpp | 22 -- src/steam/control/command-mutation.hpp | 15 -- src/steam/control/command-op-closure.hpp | 21 -- src/steam/control/command-simple-closure.hpp | 24 -- src/steam/control/command-storage-holder.hpp | 25 --- src/steam/control/command.cpp | 7 - src/steam/control/command.hpp | 1 - src/steam/control/memento-tie.hpp | 15 -- src/steam/engine/type-handler.hpp | 1 - .../steam/control/command-argument-test.cpp | 45 ---- .../control/command-clone-builder-test.cpp | 5 - .../steam/control/command-equality-test.cpp | 167 +------------- .../steam/control/command-registry-test.cpp | 3 - tests/core/steam/control/memento-tie-test.cpp | 45 ---- tests/library/functor-util-test.cpp | 212 ------------------ tests/library/meta/function-erasure-test.cpp | 47 ---- wiki/thinkPad.ichthyo.mm | 86 ++++--- 23 files changed, 46 insertions(+), 970 deletions(-) delete mode 100644 src/lib/functor-util.hpp delete mode 100644 tests/library/functor-util-test.cpp 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/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/functor-util.hpp b/src/lib/functor-util.hpp deleted file mode 100644 index 92ed46633..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/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/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/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 7b1191976..33f3dd5f2 100644 --- a/src/steam/control/command.hpp +++ b/src/steam/control/command.hpp @@ -223,7 +223,6 @@ namespace control { private: void setArguments (Arguments&); void setArguments (lib::diff::Rec const&); - static bool equivalentImpl (Command const&, Command const&); }; 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 cf49bcd9e..0eae6666f 100644 --- a/src/steam/engine/type-handler.hpp +++ b/src/steam/engine/type-handler.hpp @@ -44,7 +44,6 @@ #include "lib/error.hpp" #include "lib/hash-value.h" -#include "lib/functor-util.hpp" #include #include 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 0e9e118fa..364b46b16 100644 --- a/tests/core/steam/control/command-registry-test.cpp +++ b/tests/core/steam/control/command-registry-test.cpp @@ -217,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; @@ -226,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/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/library/functor-util-test.cpp b/tests/library/functor-util-test.cpp deleted file mode 100644 index ad1e11c7b..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/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/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index cdba0726f..7cbd61f5e 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -44930,7 +44930,8 @@
- + + @@ -45162,8 +45163,8 @@ - - + + @@ -45255,11 +45256,11 @@ - - - - - + + + + + @@ -45731,7 +45732,8 @@ - + + @@ -45763,7 +45765,7 @@ - + @@ -45779,7 +45781,7 @@ - + @@ -45793,8 +45795,6 @@ - - @@ -45939,11 +45939,10 @@ - - - - - + + + + @@ -45956,10 +45955,9 @@ er wollte "versuchen, Lumiera zu bauen"

- -
- - + + + @@ -45988,8 +45986,7 @@ wann sind Funktoren äquivalent ??

- - + @@ -46008,8 +46005,7 @@ sei die Dose offen...

- -
+
@@ -46042,8 +46038,7 @@ aber ansonsten alle validen definierten Funktionen untereinander verschieden sind.

- - +
@@ -46053,9 +46048,9 @@
- + - + @@ -46073,8 +46068,7 @@ sonst auf Äquivalenz getestet

- - +
@@ -46087,8 +46081,7 @@ und genau das Letztere ist nicht garantiert korrekt implementierbar

- - +
@@ -46110,12 +46103,11 @@ Selbst verschiedene Closures haben selbst die noch eine eindeutige Identität

- - +
- - + + @@ -46142,8 +46134,7 @@ d.h. wir brauchen keine Äquivalenz?

- - +
@@ -46163,20 +46154,23 @@
- - + + - - + + - - + +
+ + + From 8ffab2f002672ab3e9228cfb6277feb3d899401d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 24 Jun 2019 02:41:02 +0200 Subject: [PATCH 07/16] Dependencies: get rid of boost-regexp (see #995) Mostly, std::regexp can be used as a drop-in replacement. Note: unfortunately ECMA regexps do not support lookbehind assertions. This lookbehind is necesary here because we want to allow parsing values from strings with additional content, which means we need explicitly to exclude mismatches due to invalid syntax. We can work around that issue like "either line start, or *not* one of these characters. Alternatively we could consider to make the match more rigid, i.e we would require the string to conain *only* the timecode spec to be parsed. --- admin/scons/Platform.py | 2 -- ...Dependencies.txt => BuildDependencies.txt} | 5 ++--- doc/technical/build/index.txt | 4 ++-- src/common/advice/binding.cpp | 10 ++++----- src/lib/cmdline.cpp | 17 +++++++-------- src/lib/cmdline.hpp | 1 + src/lib/query-util.cpp | 21 ++++++++++--------- src/lib/searchpath.cpp | 4 +++- src/lib/searchpath.hpp | 14 +++++-------- src/lib/time/timecode.cpp | 18 ++++++++-------- src/steam/asset/media.cpp | 12 +++++------ tests/basics/time/time-parsing-test.cpp | 1 + 12 files changed, 53 insertions(+), 56 deletions(-) rename doc/technical/build/{Dependencies.txt => BuildDependencies.txt} (98%) diff --git a/admin/scons/Platform.py b/admin/scons/Platform.py index 8060c4630..3da22293f 100644 --- a/admin/scons/Platform.py +++ b/admin/scons/Platform.py @@ -92,8 +92,6 @@ def configure(env): problems.append('We need the boost::system support library (including binary lib).') if not conf.CheckLibWithHeader('boost_filesystem','boost/filesystem.hpp','C++'): problems.append('We need the boost::filesystem lib (including binary lib for linking).') - if not conf.CheckLibWithHeader('boost_regex','boost/regex.hpp','C++'): - problems.append('We need the boost regular expression lib (incl. binary lib for linking).') if not conf.CheckPkgConfig('gavl', '1.4'): diff --git a/doc/technical/build/Dependencies.txt b/doc/technical/build/BuildDependencies.txt similarity index 98% rename from doc/technical/build/Dependencies.txt rename to doc/technical/build/BuildDependencies.txt index 29b6b16c1..de350c20d 100644 --- a/doc/technical/build/Dependencies.txt +++ b/doc/technical/build/BuildDependencies.txt @@ -1,5 +1,5 @@ -Dependencies -============ +Build Dependencies +================== :Author: core-devs :Date: 11/2015 :toc: @@ -66,7 +66,6 @@ Languages and Tools - libboost-program-options-dev - libboost-program-options-dev - libboost-filesystem-dev - - libboost-regex-dev * Script languages - Python (*2.7*) for build scripts 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/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/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/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/time/timecode.cpp b/src/lib/time/timecode.cpp index a375d825d..2e30a9e79 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,8 +119,8 @@ namespace time { TimeValue Seconds::parse (string const& seconds, QuantR grid) { - static regex fracSecs_parser ("(? (match[N]) smatch match; 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/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) } From e639558e2c91b58706dbe9202e96341c919c37a3 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 15 Feb 2020 19:34:57 +0100 Subject: [PATCH 08/16] Debian-Buster: compile Fix for GCC-8 Yeah... we are there, finally! --- src/lib/iter-tree-explorer.hpp | 3 +- wiki/thinkPad.ichthyo.mm | 323 +++++++++++++++++++-------------- 2 files changed, 189 insertions(+), 137 deletions(-) diff --git a/src/lib/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index e28be857a..4d4918a61 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -446,7 +446,8 @@ namespace lib { namespace iter_explorer { // Implementation of Iterator decorating layers... - constexpr auto ACCEPT_ALL = [](auto){return true;}; + /*constexpr*/ ///////////////////////////////////////////////////////////TICKET #1138 : lambdas are literal only in C++17 + auto ACCEPT_ALL = [](auto){return true;}; /** * @internal technical details of binding a functor into the TreeExplorer. diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 7cbd61f5e..ede328825 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -44515,13 +44515,16 @@ - + + + + + + - + - - - + @@ -44533,7 +44536,7 @@ - + @@ -44545,7 +44548,7 @@ - + @@ -44571,7 +44574,7 @@ - + @@ -44583,12 +44586,12 @@ - - - + + + - + @@ -44600,10 +44603,10 @@ - - - - + + + + @@ -44616,7 +44619,7 @@ - + @@ -44630,7 +44633,7 @@

- + @@ -44642,7 +44645,7 @@ - + @@ -44657,7 +44660,7 @@ - + @@ -44669,9 +44672,9 @@ - - - + + + @@ -44683,7 +44686,7 @@ - + @@ -44698,7 +44701,7 @@ - + @@ -44713,7 +44716,7 @@ - + @@ -44734,9 +44737,9 @@ - + - + @@ -44752,10 +44755,10 @@ - + - + @@ -44774,11 +44777,11 @@ - - + + - + @@ -44790,9 +44793,9 @@ - - - + + + @@ -44804,9 +44807,9 @@ - + - + @@ -44819,7 +44822,7 @@ - + @@ -44832,7 +44835,7 @@ - + @@ -44868,33 +44871,33 @@ - - + + - - - + + + - + - - + + - + - + @@ -44913,7 +44916,7 @@ - + @@ -44926,10 +44929,57 @@ - + + + + + + + + + + + + + + + + + + + + + + +
    +
  • + sinnvollen Zustand erreichen: zumindest das neue GUI sollte wieder starten +
  • +
  • + dann Paket aktualisieren und neu bauen +
  • +
+ + +
+ +
+ + + +
+ + + + + + + + + @@ -45163,13 +45213,13 @@
- - - - + + + + - - + + @@ -45210,8 +45260,7 @@ Grund ist die Umstellung auf inline-Storage

- -
+
@@ -45227,14 +45276,13 @@ da wir nun eine vollwertige String-Tabelle haben

- - +
- - + + @@ -45252,8 +45300,7 @@ waren nur minimale Anpassungen

- - +
@@ -45264,13 +45311,50 @@
+ + + + + + + + + + + + + + + + + + +

+ 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 +

+ +
+ +
+
+ + + + + + + + + +
+
- - - + + + @@ -45283,8 +45367,7 @@ - - + @@ -45294,13 +45377,13 @@ hier nach offensichtlich obsoleter Info checken

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

-
- + +
- + @@ -45317,16 +45400,13 @@

- - - + - - + @@ -45338,13 +45418,12 @@ - - + @@ -45365,18 +45444,11 @@ - - - + + + - - - - - - - - + @@ -45391,7 +45463,6 @@ - @@ -45403,7 +45474,7 @@ - + @@ -45418,26 +45489,16 @@ - - + - - - - - - - + + - - - - - - + + @@ -45457,7 +45518,7 @@ - + @@ -45468,7 +45529,7 @@

- + @@ -45488,9 +45549,8 @@ - - - + + @@ -45549,8 +45609,8 @@ - - + + @@ -45620,10 +45680,10 @@ - - + + - + @@ -45634,28 +45694,19 @@

-
- - - - + + + + - - - - - - - - + - - - + + From 8867ae55ad1a4ba48d3413c17af0692a1ddcd9a0 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sun, 16 Feb 2020 01:20:21 +0100 Subject: [PATCH 09/16] Clean-up: problematic function signature GCC8 now spots and warns about such mismatches. And we should take such warnings seriously; code produced by the newer GCC versions tends to segfault, especially under -O2 and above, when a return statement is actually missing, even if the return value is actually not used at call site. Here, a functor to unlock the active "guard" is passed into a macro construct, which basically allows to abstract the various kinds of "guards", be it mutex, condition variable or the like. Seemingly, the intention was to deal with a failure when unlocking -- however all the real implementations prefer to kill the whole application without much ado. --- src/lib/sectionlock.h | 2 +- wiki/thinkPad.ichthyo.mm | 30 ++++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) 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/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index ede328825..fa8b7458e 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -44943,9 +44943,35 @@ - - + + + + + + + + + + + + + + + + + + + +

+ 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. +

+ + +
+ +
+
From 38837da65e5e3ebf0d0048531e6beeaec8ec0dc6 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 17 Feb 2020 02:36:54 +0100 Subject: [PATCH 10/16] Timehandling: choose safer representation for fractional seconds (closes #939) When drafting the time handling framework some years ago, I foresaw the possible danger of mixing up numbers relating to fractional seconds, with other plain numbers intended as frame counts or as micro ticks. Thus I deliberately picked an incompatible integer type for FSecs = boost::rational However, using long is problematic in itself, since its actual bit length is not fixed, and especially on 32bit platforms long is quite surprisingly defined to be the same as int. However, meanwhile, using the new C++ features, I have blocked pretty much any possible implicit conversion path, requiring explicit conversions in the relevant ctor invocations. So, after weighting in the alternatives, FSecs is now defined as boost::rational. --- src/lib/time/grid.hpp | 15 +- src/lib/time/time.cpp | 38 ++++- src/lib/time/timecode.cpp | 4 +- src/lib/time/timevalue.hpp | 29 ++-- tests/basics/time/quantiser-basics-test.cpp | 8 +- .../asset/meta/time-grid-basics-test.cpp | 18 +-- wiki/thinkPad.ichthyo.mm | 150 ++++++++++++++++-- 7 files changed, 214 insertions(+), 48 deletions(-) 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 2e30a9e79..a1f4ebee6 100644 --- a/src/lib/time/timecode.cpp +++ b/src/lib/time/timecode.cpp @@ -122,14 +122,14 @@ namespace time { static regex fracSecs_parser ("(?:^|[^\\./\\d\\-])(\\-?\\d+)(?:([\\-\\+]\\d+)?/(\\d+))?sec"); //__no leading[./-\d] number [+-] number '/' number 'sec' - #define SUB_EXPR(N) lexical_cast (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 0755e4969..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; @@ -576,7 +574,7 @@ namespace time { inline FSecs operator/ (int n, FrameRate rate) { - return n / boost::rational_cast (rate); + return FSecs{ n*rate.denominator(), rate.numerator()}; } @@ -621,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 @@ -654,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/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/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/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index fa8b7458e..2509c69fc 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -44967,8 +44967,7 @@ 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.

- -
+
@@ -44989,8 +44988,7 @@ - - +
@@ -45363,9 +45361,144 @@
- - - + + + + + + + + +

+ 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 +

+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -45406,8 +45539,7 @@ WICHTIG: keine vorgreifende Infos publizieren!!!!!

- - +
From 3cfe5a13b19a0532f7d3365b3fc91085bd0a8789 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Mon, 17 Feb 2020 03:32:43 +0100 Subject: [PATCH 11/16] fix failing test - boost::format is getting better "%broken" is not broken anymore, but renders a boolean, and we configured the formatter not to complain on missing values. Fortunately "%madness" is still broken ;-) --- tests/library/format-string-test.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) 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")); } From 577592c66eab5840d9ad4020f3a1b4092b2e579d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 18 Feb 2020 04:16:03 +0100 Subject: [PATCH 12/16] C++17: isolate problematic code segments (see Ticket #1138) as it turns out, "almost" the whole codebase compiles in C++17 mode. with the exception of two metaprogramming-related problems: - our "duck detector" for STL containers does not trigger anymore - the Metafunction to dissect Function sigantures (meta::_Fun) flounders --- src/common/subsystem-runner.hpp | 3 + src/lib/format-util.hpp | 3 + src/stage/workspace/dock-area.cpp | 3 + src/stage/workspace/panel-manager.cpp | 3 + src/steam/asset.cpp | 3 + src/steam/play/play-service.cpp | 3 + .../engine/dispatcher-interface-test.cpp | 3 + tests/library/diff/mutation-message-test.cpp | 3 + .../diff/tree-mutator-binding-test.cpp | 12 +++ tests/library/format-helper-test.cpp | 6 ++ tests/library/item-wrapper-test.cpp | 3 + tests/library/iter-chain-search-test.cpp | 6 ++ tests/library/iter-tree-explorer-test.cpp | 10 ++ tests/library/util-collection-test.cpp | 3 + tests/library/util-foreach-test.cpp | 6 ++ tests/library/verb-visitor-dispatch-test.cpp | 3 + tests/stage/test/test-nexus.cpp | 2 + wiki/thinkPad.ichthyo.mm | 96 ++++++++++++++++++- 18 files changed, 168 insertions(+), 3 deletions(-) diff --git a/src/common/subsystem-runner.hpp b/src/common/subsystem-runner.hpp index fe9808d1d..1d015ea40 100644 --- a/src/common/subsystem-runner.hpp +++ b/src/common/subsystem-runner.hpp @@ -193,7 +193,10 @@ namespace lumiera { throw error::Logic("Subsystem "+string(*susy)+" failed to start"); } +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility if (not and_all (susy->getPrerequisites(), isRunning() )) +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + if (true) ////FIXME { susy->triggerShutdown(); throw error::State("Unable to start all prerequisites of Subsystem "+string(*susy)); diff --git a/src/lib/format-util.hpp b/src/lib/format-util.hpp index 3d926e9f5..099fb1d0f 100644 --- a/src/lib/format-util.hpp +++ b/src/lib/format-util.hpp @@ -194,6 +194,7 @@ namespace util { using Coll = typename lib::meta::Strip::TypePlain; _RangeIter range(std::forward(coll)); +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto strings = stringify (std::move (range.iter)); if (!strings) return ""; @@ -205,6 +206,8 @@ namespace util { size_t len = buffer.str().length(); ASSERT (len >= delim.length()); return buffer.str().substr(0, len - delim.length()); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + return "bääh"; } template diff --git a/src/stage/workspace/dock-area.cpp b/src/stage/workspace/dock-area.cpp index a78d0fe92..ce990ad16 100644 --- a/src/stage/workspace/dock-area.cpp +++ b/src/stage/workspace/dock-area.cpp @@ -147,10 +147,13 @@ namespace workspace { bool DockArea::hasPanel (const int description_index) { +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility return util::has_any (panels_, [=](panel::Panel* panel) { return getPanelType(panel) == description_index; }); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + return false; /////FIXME } panel::Panel& diff --git a/src/stage/workspace/panel-manager.cpp b/src/stage/workspace/panel-manager.cpp index 92593695d..767cef434 100644 --- a/src/stage/workspace/panel-manager.cpp +++ b/src/stage/workspace/panel-manager.cpp @@ -140,10 +140,13 @@ namespace workspace { bool PanelManager::hasPanel (const int description_index) { +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility return util::has_any (panels_, [=](panel::Panel* panel) { return getPanelType(panel) == description_index; }); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + return false; //////FIXME } panel::Panel& diff --git a/src/steam/asset.cpp b/src/steam/asset.cpp index 85055c5c8..d01f789f0 100644 --- a/src/steam/asset.cpp +++ b/src/steam/asset.cpp @@ -117,7 +117,10 @@ namespace asset { bool all_parents_enabled (const vector& parents) { +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility return and_all (parents, check_isActive); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + return false; } /** diff --git a/src/steam/play/play-service.cpp b/src/steam/play/play-service.cpp index be8675eec..13d181d41 100644 --- a/src/steam/play/play-service.cpp +++ b/src/steam/play/play-service.cpp @@ -119,7 +119,10 @@ namespace play { bool isActive() const { +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility return not and_all (processes_, isDead); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + return false; } private: diff --git a/tests/core/steam/engine/dispatcher-interface-test.cpp b/tests/core/steam/engine/dispatcher-interface-test.cpp index e2998336e..15ff5239b 100644 --- a/tests/core/steam/engine/dispatcher-interface-test.cpp +++ b/tests/core/steam/engine/dispatcher-interface-test.cpp @@ -211,7 +211,10 @@ namespace test { vector plannedChunk; lib::append_all (jobs, plannedChunk); +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility Duration coveredTime (Offset(refPoint, last(plannedChunk).getNominalTime())); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + Duration coveredTime (lib::time::FSecs(23,55)); /////////////////////FIXME CHECK (coveredTime >= timings.getPlanningChunkDuration()); ///TODO nachfolgendes muß komplett umgeschrieben werden diff --git a/tests/library/diff/mutation-message-test.cpp b/tests/library/diff/mutation-message-test.cpp index 3bad00977..01fe8cf12 100644 --- a/tests/library/diff/mutation-message-test.cpp +++ b/tests/library/diff/mutation-message-test.cpp @@ -276,6 +276,7 @@ namespace test{ ,set(ATTRIB1) ,del(CHILD_T)}), steps); +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility diffMsg = MutationMessage{steps}; CHECK (!isnil (diffMsg)); @@ -283,6 +284,8 @@ namespace test{ CHECK (set(ATTRIB1) == *++diffMsg); CHECK (del(CHILD_T) == *++diffMsg); CHECK (isnil (++diffMsg)); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); } diff --git a/tests/library/diff/tree-mutator-binding-test.cpp b/tests/library/diff/tree-mutator-binding-test.cpp index 8059810b8..093427a08 100644 --- a/tests/library/diff/tree-mutator-binding-test.cpp +++ b/tests/library/diff/tree-mutator-binding-test.cpp @@ -408,7 +408,10 @@ namespace test{ mutator1.injectNew (ATTRIB1); CHECK (!isnil (target)); +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility CHECK (contains(join(target), "≺α∣1≻")); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); mutator1.injectNew (ATTRIB3); mutator1.injectNew (ATTRIB3); @@ -417,6 +420,7 @@ namespace test{ mutator1.injectNew (CHILD_T); CHECK (mutator1.completeScope()); +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto contents = stringify(eachElm(target)); CHECK ("≺α∣1≻" == *contents); ++contents; @@ -431,6 +435,8 @@ namespace test{ CHECK (contains(*contents, "∣78:56:34.012≻")); ++contents; CHECK (isnil (contents)); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); cout << "injected......" << join(target) <; @@ -166,6 +169,7 @@ namespace test { ++nn; CHECK (6 == *nn); +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto sn = stringify (nn); CHECK ("6" == *sn); ++sn; @@ -182,6 +186,8 @@ namespace test { CHECK ("9" == *sn); ++sn; CHECK (isnil (sn)); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); } diff --git a/tests/library/item-wrapper-test.cpp b/tests/library/item-wrapper-test.cpp index f336e066d..598d2b811 100644 --- a/tests/library/item-wrapper-test.cpp +++ b/tests/library/item-wrapper-test.cpp @@ -312,6 +312,7 @@ namespace test{ void verifyFunctionResult() { +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility FunctionResult randomVal (std::rand); // function was never invoked, thus the remembered result is NIL @@ -330,6 +331,8 @@ namespace test{ CHECK (v2 == *randomVal); CHECK (v2 == *randomVal); CHECK (v1 != *randomVal); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); } diff --git a/tests/library/iter-chain-search-test.cpp b/tests/library/iter-chain-search-test.cpp index 714af1695..a4e83ec66 100644 --- a/tests/library/iter-chain-search-test.cpp +++ b/tests/library/iter-chain-search-test.cpp @@ -117,6 +117,7 @@ namespace test{ void simpleSearch () { +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto search = chainSearch(SPAM) .search("bacon") .search("tomato"); @@ -138,6 +139,8 @@ namespace test{ CHECK (not search); CHECK (isnil (search)); VERIFY_ERROR (ITER_EXHAUST, *search); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); } @@ -152,6 +155,7 @@ namespace test{ void chainedIteration () { +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto search = chainSearch(SPAM) // Note: 1st filter step picks all s-words .search([](string const& str){ return startsWith (str, "s"); }); @@ -175,6 +179,8 @@ namespace test{ "bacon-tomato-and-" // any non-spam behind the 3rd spam "tomato-and" // any non-spam behind the 4th spam ""); // and any non-spam behind the final spam +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); } diff --git a/tests/library/iter-tree-explorer-test.cpp b/tests/library/iter-tree-explorer-test.cpp index cb8fc8470..1f657e38f 100644 --- a/tests/library/iter-tree-explorer-test.cpp +++ b/tests/library/iter-tree-explorer-test.cpp @@ -340,10 +340,13 @@ namespace test{ CHECK (materialise(jj) == "3--5-8--13"); // can even adapt STL container automatically +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto kk = treeExplore(numz); CHECK (!isnil (kk)); CHECK (1 == *kk); CHECK (materialise(kk) == "1--2-3--5-8--13"); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); } @@ -392,10 +395,12 @@ namespace test{ .expand([](uint j){ return CountDown{j-1}; }) // expand-functor: Val > StateCore ); +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility verify_treeExpandingIterator( treeExplore(CountDown{5}) .expand([](uint j){ return NumberSequence{j-1}; }) // expand-functor: Val > Iter ); // NOTE: different Iterator type than the source! +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility // lambda with side-effect and return type different from source iter vector> childBuffer; @@ -408,10 +413,12 @@ namespace test{ return childNumbz; }; +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility verify_treeExpandingIterator( treeExplore(CountDown{5}) .expand(expandIntoChildBuffer) // expand-functor: Val > STL-container& ); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility // test routine called the expansion functor five times CHECK (5 == childBuffer.size()); @@ -579,6 +586,7 @@ namespace test{ // demonstrate chaining of several transformation layers vector numz{1,-2,3,-5,8,-13}; +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility CHECK ("≺1≻-≺-2≻-≺3≻-≺-5≻-≺8≻-≺-13≻" == materialise (treeExplore(numz) .transform(formatify)) ); @@ -591,6 +599,8 @@ namespace test{ .transform(multiply) .transform(formatify) .transform(formatify)) ); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); // demonstrate the functor is evaluated only once per step diff --git a/tests/library/util-collection-test.cpp b/tests/library/util-collection-test.cpp index eb6292598..5d2a7f71f 100644 --- a/tests/library/util-collection-test.cpp +++ b/tests/library/util-collection-test.cpp @@ -96,8 +96,11 @@ namespace test { VecI container = someNumberz (NUM_ELMS); RangeI iterator(container.begin(), container.end()); +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility verify_accessFirstLast (container, NUM_ELMS); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility verify_accessFirstLast (iterator, NUM_ELMS); + UNIMPLEMENTED ("C++17"); } diff --git a/tests/library/util-foreach-test.cpp b/tests/library/util-foreach-test.cpp index 5be9fc175..c500e78ec 100644 --- a/tests/library/util-foreach-test.cpp +++ b/tests/library/util-foreach-test.cpp @@ -131,6 +131,7 @@ namespace test { VecI container = buildTestNumberz (NUM_ELMS); RangeI iterator(container.begin(), container.end()); +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility check_foreach_plain (container); check_foreach_plain (iterator); @@ -151,6 +152,8 @@ namespace test { CHECK (int(NUM_ELMS) ==container[0]); check_ref_argument_bind (container); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); CHECK (int(NUM_ELMS) ==container[0]); check_ref_argument_bind (iterator); @@ -410,6 +413,7 @@ namespace test { // fed the element pointer as "this" pointer of the member function for_each (elmPtrs, &TestElm::operation, _1 ); _NL_ +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility and_all (elmPtrs, &TestElm::operation, _1 ); _NL_ has_any (elmPtrs, &TestElm::operation, _1 ); _NL_ @@ -417,6 +421,8 @@ namespace test { for_each (elms, &TestElm::operation, _1 ); _NL_ and_all (elms, &TestElm::operation, _1 ); _NL_ has_any (elms, &TestElm::operation, _1 ); _NL_ +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); // note: it seems not to be possible to create a binder, which takes the "*this"-Argument by ref } diff --git a/tests/library/verb-visitor-dispatch-test.cpp b/tests/library/verb-visitor-dispatch-test.cpp index bd50835f6..2ff6922ed 100644 --- a/tests/library/verb-visitor-dispatch-test.cpp +++ b/tests/library/verb-visitor-dispatch-test.cpp @@ -198,6 +198,7 @@ namespace test{ { VerboseRenderer verbose; DiagnosticRenderer diagnostic; +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto render = [&](Receiver& renderer) { return join (lib::treeExplore(tokens) @@ -210,6 +211,8 @@ namespace test{ CHECK (render(diagnostic) == "woof(false,3)-honk(quaack)-honk(Hoonk)-woof(true,2)-moo(3)-meh()"); CHECK (render(verbose) == "haw-hawhaw-hawhaw-hawhaw-haw-quaack-quaack!-Hoonk-Hoonk!-Woof..Woof..-Moo__Moo__Moo-Meh?"); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility + UNIMPLEMENTED ("C++17"); } diff --git a/tests/stage/test/test-nexus.cpp b/tests/stage/test/test-nexus.cpp index 2eb38c2fd..508372757 100644 --- a/tests/stage/test/test-nexus.cpp +++ b/tests/stage/test/test-nexus.cpp @@ -496,9 +496,11 @@ namespace test{ { EventLog::ArgSeq strings; strings.reserve (argData.childSize()); +#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility append_all (transformIterator (childData (argData.scope()) , util::toString) ,strings); +#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility return strings; } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 2509c69fc..23dd611aa 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -45338,8 +45338,8 @@ - - + + @@ -45361,7 +45361,7 @@ - + @@ -45504,6 +45504,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ 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>' +

+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 8c12e88fd37643be077a066f1f65ef03182b56ae Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 21 Feb 2020 18:45:51 +0100 Subject: [PATCH 13/16] C++17: fix detector for STL container iterability the reason for the failure, as it turned out, is that 'noexcept' is part of the function signature since C++17 And, since typically a STL container has const and non-const variants of the begin() and end() function, the match to a member function pointer became ambuguous, when probing with a signature without 'noexcept' However, we deliberately want to support "any STL container like" types, and this IMHO should include types with a possibly throwing iterator. The rationale is, sometimes we want to expose some element *generator* behind a container-like interface. At this point I did an investigation if we can emulate something in the way of a Concept -- i.e. rather than checking for the presence of some functions on the interface, better try to cover the necessary behaviour, like in a type class. Unfortunately, while doable, this turns out to become quite technical; and this highlights why the C++20 concepts are such an important addition to the language. So for the time being, we'll amend the existing solution and look ahead to C++20 --- src/common/subsystem-runner.hpp | 3 - src/lib/meta/trait.hpp | 56 ++++- src/stage/workspace/dock-area.cpp | 3 - src/stage/workspace/panel-manager.cpp | 3 - src/steam/asset.cpp | 3 - src/steam/play/play-service.cpp | 3 - .../engine/dispatcher-interface-test.cpp | 5 +- tests/library/diff/mutation-message-test.cpp | 3 - tests/library/iter-chain-search-test.cpp | 6 - tests/library/iter-tree-explorer-test.cpp | 10 - tests/library/util-collection-test.cpp | 3 - tests/library/util-foreach-test.cpp | 6 - tests/library/verb-visitor-dispatch-test.cpp | 3 - wiki/thinkPad.ichthyo.mm | 212 +++++++++++++++++- 14 files changed, 263 insertions(+), 56 deletions(-) diff --git a/src/common/subsystem-runner.hpp b/src/common/subsystem-runner.hpp index 1d015ea40..fe9808d1d 100644 --- a/src/common/subsystem-runner.hpp +++ b/src/common/subsystem-runner.hpp @@ -193,10 +193,7 @@ namespace lumiera { throw error::Logic("Subsystem "+string(*susy)+" failed to start"); } -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility if (not and_all (susy->getPrerequisites(), isRunning() )) -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - if (true) ////FIXME { susy->triggerShutdown(); throw error::State("Unable to start all prerequisites of Subsystem "+string(*susy)); 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/stage/workspace/dock-area.cpp b/src/stage/workspace/dock-area.cpp index ce990ad16..a78d0fe92 100644 --- a/src/stage/workspace/dock-area.cpp +++ b/src/stage/workspace/dock-area.cpp @@ -147,13 +147,10 @@ namespace workspace { bool DockArea::hasPanel (const int description_index) { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility return util::has_any (panels_, [=](panel::Panel* panel) { return getPanelType(panel) == description_index; }); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - return false; /////FIXME } panel::Panel& diff --git a/src/stage/workspace/panel-manager.cpp b/src/stage/workspace/panel-manager.cpp index 767cef434..92593695d 100644 --- a/src/stage/workspace/panel-manager.cpp +++ b/src/stage/workspace/panel-manager.cpp @@ -140,13 +140,10 @@ namespace workspace { bool PanelManager::hasPanel (const int description_index) { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility return util::has_any (panels_, [=](panel::Panel* panel) { return getPanelType(panel) == description_index; }); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - return false; //////FIXME } panel::Panel& diff --git a/src/steam/asset.cpp b/src/steam/asset.cpp index d01f789f0..85055c5c8 100644 --- a/src/steam/asset.cpp +++ b/src/steam/asset.cpp @@ -117,10 +117,7 @@ namespace asset { bool all_parents_enabled (const vector& parents) { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility return and_all (parents, check_isActive); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - return false; } /** diff --git a/src/steam/play/play-service.cpp b/src/steam/play/play-service.cpp index 13d181d41..be8675eec 100644 --- a/src/steam/play/play-service.cpp +++ b/src/steam/play/play-service.cpp @@ -119,10 +119,7 @@ namespace play { bool isActive() const { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility return not and_all (processes_, isDead); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - return false; } private: diff --git a/tests/core/steam/engine/dispatcher-interface-test.cpp b/tests/core/steam/engine/dispatcher-interface-test.cpp index 15ff5239b..62ebdc8c2 100644 --- a/tests/core/steam/engine/dispatcher-interface-test.cpp +++ b/tests/core/steam/engine/dispatcher-interface-test.cpp @@ -211,10 +211,7 @@ namespace test { vector plannedChunk; lib::append_all (jobs, plannedChunk); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility Duration coveredTime (Offset(refPoint, last(plannedChunk).getNominalTime())); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - Duration coveredTime (lib::time::FSecs(23,55)); /////////////////////FIXME CHECK (coveredTime >= timings.getPlanningChunkDuration()); ///TODO nachfolgendes muß komplett umgeschrieben werden @@ -223,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/mutation-message-test.cpp b/tests/library/diff/mutation-message-test.cpp index 01fe8cf12..3bad00977 100644 --- a/tests/library/diff/mutation-message-test.cpp +++ b/tests/library/diff/mutation-message-test.cpp @@ -276,7 +276,6 @@ namespace test{ ,set(ATTRIB1) ,del(CHILD_T)}), steps); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility diffMsg = MutationMessage{steps}; CHECK (!isnil (diffMsg)); @@ -284,8 +283,6 @@ namespace test{ CHECK (set(ATTRIB1) == *++diffMsg); CHECK (del(CHILD_T) == *++diffMsg); CHECK (isnil (++diffMsg)); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); } diff --git a/tests/library/iter-chain-search-test.cpp b/tests/library/iter-chain-search-test.cpp index a4e83ec66..714af1695 100644 --- a/tests/library/iter-chain-search-test.cpp +++ b/tests/library/iter-chain-search-test.cpp @@ -117,7 +117,6 @@ namespace test{ void simpleSearch () { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto search = chainSearch(SPAM) .search("bacon") .search("tomato"); @@ -139,8 +138,6 @@ namespace test{ CHECK (not search); CHECK (isnil (search)); VERIFY_ERROR (ITER_EXHAUST, *search); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); } @@ -155,7 +152,6 @@ namespace test{ void chainedIteration () { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto search = chainSearch(SPAM) // Note: 1st filter step picks all s-words .search([](string const& str){ return startsWith (str, "s"); }); @@ -179,8 +175,6 @@ namespace test{ "bacon-tomato-and-" // any non-spam behind the 3rd spam "tomato-and" // any non-spam behind the 4th spam ""); // and any non-spam behind the final spam -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); } diff --git a/tests/library/iter-tree-explorer-test.cpp b/tests/library/iter-tree-explorer-test.cpp index 1f657e38f..cb8fc8470 100644 --- a/tests/library/iter-tree-explorer-test.cpp +++ b/tests/library/iter-tree-explorer-test.cpp @@ -340,13 +340,10 @@ namespace test{ CHECK (materialise(jj) == "3--5-8--13"); // can even adapt STL container automatically -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto kk = treeExplore(numz); CHECK (!isnil (kk)); CHECK (1 == *kk); CHECK (materialise(kk) == "1--2-3--5-8--13"); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); } @@ -395,12 +392,10 @@ namespace test{ .expand([](uint j){ return CountDown{j-1}; }) // expand-functor: Val > StateCore ); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility verify_treeExpandingIterator( treeExplore(CountDown{5}) .expand([](uint j){ return NumberSequence{j-1}; }) // expand-functor: Val > Iter ); // NOTE: different Iterator type than the source! -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility // lambda with side-effect and return type different from source iter vector> childBuffer; @@ -413,12 +408,10 @@ namespace test{ return childNumbz; }; -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility verify_treeExpandingIterator( treeExplore(CountDown{5}) .expand(expandIntoChildBuffer) // expand-functor: Val > STL-container& ); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility // test routine called the expansion functor five times CHECK (5 == childBuffer.size()); @@ -586,7 +579,6 @@ namespace test{ // demonstrate chaining of several transformation layers vector numz{1,-2,3,-5,8,-13}; -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility CHECK ("≺1≻-≺-2≻-≺3≻-≺-5≻-≺8≻-≺-13≻" == materialise (treeExplore(numz) .transform(formatify)) ); @@ -599,8 +591,6 @@ namespace test{ .transform(multiply) .transform(formatify) .transform(formatify)) ); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); // demonstrate the functor is evaluated only once per step diff --git a/tests/library/util-collection-test.cpp b/tests/library/util-collection-test.cpp index 5d2a7f71f..eb6292598 100644 --- a/tests/library/util-collection-test.cpp +++ b/tests/library/util-collection-test.cpp @@ -96,11 +96,8 @@ namespace test { VecI container = someNumberz (NUM_ELMS); RangeI iterator(container.begin(), container.end()); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility verify_accessFirstLast (container, NUM_ELMS); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility verify_accessFirstLast (iterator, NUM_ELMS); - UNIMPLEMENTED ("C++17"); } diff --git a/tests/library/util-foreach-test.cpp b/tests/library/util-foreach-test.cpp index c500e78ec..5be9fc175 100644 --- a/tests/library/util-foreach-test.cpp +++ b/tests/library/util-foreach-test.cpp @@ -131,7 +131,6 @@ namespace test { VecI container = buildTestNumberz (NUM_ELMS); RangeI iterator(container.begin(), container.end()); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility check_foreach_plain (container); check_foreach_plain (iterator); @@ -152,8 +151,6 @@ namespace test { CHECK (int(NUM_ELMS) ==container[0]); check_ref_argument_bind (container); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); CHECK (int(NUM_ELMS) ==container[0]); check_ref_argument_bind (iterator); @@ -413,7 +410,6 @@ namespace test { // fed the element pointer as "this" pointer of the member function for_each (elmPtrs, &TestElm::operation, _1 ); _NL_ -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility and_all (elmPtrs, &TestElm::operation, _1 ); _NL_ has_any (elmPtrs, &TestElm::operation, _1 ); _NL_ @@ -421,8 +417,6 @@ namespace test { for_each (elms, &TestElm::operation, _1 ); _NL_ and_all (elms, &TestElm::operation, _1 ); _NL_ has_any (elms, &TestElm::operation, _1 ); _NL_ -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); // note: it seems not to be possible to create a binder, which takes the "*this"-Argument by ref } diff --git a/tests/library/verb-visitor-dispatch-test.cpp b/tests/library/verb-visitor-dispatch-test.cpp index 2ff6922ed..bd50835f6 100644 --- a/tests/library/verb-visitor-dispatch-test.cpp +++ b/tests/library/verb-visitor-dispatch-test.cpp @@ -198,7 +198,6 @@ namespace test{ { VerboseRenderer verbose; DiagnosticRenderer diagnostic; -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto render = [&](Receiver& renderer) { return join (lib::treeExplore(tokens) @@ -211,8 +210,6 @@ namespace test{ CHECK (render(diagnostic) == "woof(false,3)-honk(quaack)-honk(Hoonk)-woof(true,2)-moo(3)-meh()"); CHECK (render(verbose) == "haw-hawhaw-hawhaw-hawhaw-haw-quaack-quaack!-Hoonk-Hoonk!-Woof..Woof..-Moo__Moo__Moo-Meh?"); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 23dd611aa..28d0baf5b 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -45528,7 +45528,9 @@ - + + + @@ -45579,21 +45581,223 @@ + + + + + + + + + + + + - - + + + + - + + + + + + + + + + + + + + + + +

+ 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 +

+ + +
+
+ + + + + + + + + + + + + + + +
From 00c9ecb659fa76450b809e3af2fc07f627a69092 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 21 Feb 2020 20:15:21 +0100 Subject: [PATCH 14/16] C++17: fix detector for function signatures failure was likewise caused by `noexcept` being part of the signature type now --- src/lib/format-util.hpp | 3 -- src/lib/meta/function.hpp | 13 +++++++ .../diff/tree-mutator-binding-test.cpp | 12 ------ tests/library/format-helper-test.cpp | 6 --- tests/library/item-wrapper-test.cpp | 3 -- tests/stage/test/test-nexus.cpp | 2 - wiki/thinkPad.ichthyo.mm | 39 ++++++++++++++++--- 7 files changed, 46 insertions(+), 32 deletions(-) diff --git a/src/lib/format-util.hpp b/src/lib/format-util.hpp index 099fb1d0f..3d926e9f5 100644 --- a/src/lib/format-util.hpp +++ b/src/lib/format-util.hpp @@ -194,7 +194,6 @@ namespace util { using Coll = typename lib::meta::Strip::TypePlain; _RangeIter range(std::forward(coll)); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto strings = stringify (std::move (range.iter)); if (!strings) return ""; @@ -206,8 +205,6 @@ namespace util { size_t len = buffer.str().length(); ASSERT (len >= delim.length()); return buffer.str().substr(0, len - delim.length()); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - return "bääh"; } template 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/tests/library/diff/tree-mutator-binding-test.cpp b/tests/library/diff/tree-mutator-binding-test.cpp index 093427a08..8059810b8 100644 --- a/tests/library/diff/tree-mutator-binding-test.cpp +++ b/tests/library/diff/tree-mutator-binding-test.cpp @@ -408,10 +408,7 @@ namespace test{ mutator1.injectNew (ATTRIB1); CHECK (!isnil (target)); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility CHECK (contains(join(target), "≺α∣1≻")); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); mutator1.injectNew (ATTRIB3); mutator1.injectNew (ATTRIB3); @@ -420,7 +417,6 @@ namespace test{ mutator1.injectNew (CHILD_T); CHECK (mutator1.completeScope()); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto contents = stringify(eachElm(target)); CHECK ("≺α∣1≻" == *contents); ++contents; @@ -435,8 +431,6 @@ namespace test{ CHECK (contains(*contents, "∣78:56:34.012≻")); ++contents; CHECK (isnil (contents)); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); cout << "injected......" << join(target) <; @@ -169,7 +166,6 @@ namespace test { ++nn; CHECK (6 == *nn); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility auto sn = stringify (nn); CHECK ("6" == *sn); ++sn; @@ -186,8 +182,6 @@ namespace test { CHECK ("9" == *sn); ++sn; CHECK (isnil (sn)); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); } diff --git a/tests/library/item-wrapper-test.cpp b/tests/library/item-wrapper-test.cpp index 598d2b811..f336e066d 100644 --- a/tests/library/item-wrapper-test.cpp +++ b/tests/library/item-wrapper-test.cpp @@ -312,7 +312,6 @@ namespace test{ void verifyFunctionResult() { -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility FunctionResult randomVal (std::rand); // function was never invoked, thus the remembered result is NIL @@ -331,8 +330,6 @@ namespace test{ CHECK (v2 == *randomVal); CHECK (v2 == *randomVal); CHECK (v1 != *randomVal); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility - UNIMPLEMENTED ("C++17"); } diff --git a/tests/stage/test/test-nexus.cpp b/tests/stage/test/test-nexus.cpp index 508372757..2eb38c2fd 100644 --- a/tests/stage/test/test-nexus.cpp +++ b/tests/stage/test/test-nexus.cpp @@ -496,11 +496,9 @@ namespace test{ { EventLog::ArgSeq strings; strings.reserve (argData.childSize()); -#if false //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility append_all (transformIterator (childData (argData.scope()) , util::toString) ,strings); -#endif //////////////////////////////////////////////////////////////////////////////////////////////////TICKET #1138 : sort out C++17 compatibility return strings; } diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 28d0baf5b..03d827485 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -45594,8 +45594,8 @@
- - + + @@ -45643,17 +45643,20 @@ - - + + + + - + + - + @@ -45797,6 +45800,30 @@ + + + + + + + + + + + + + + + +

+ mit const und volatile... +

+ + +
+ +
+
From beb8406abe89cfbda4b80d364786410cd5789d07 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 21 Feb 2020 21:08:31 +0100 Subject: [PATCH 15/16] Project: switch to C++17 (closes: #1138) Signed-off-by: Ichthyostega --- admin/scons/Setup.py | 2 +- doc/technical/build/BuildDependencies.txt | 17 +-- doc/technical/code/c++11.txt | 29 ++---- doc/technical/howto/IdeSetup.txt | 16 ++- doc/user/tutorials/building.txt | 21 +--- doc/user/tutorials/contributing.txt | 1 - wiki/thinkPad.ichthyo.mm | 120 ++++++++++++---------- 7 files changed, 98 insertions(+), 108 deletions(-) diff --git a/admin/scons/Setup.py b/admin/scons/Setup.py index 510e6b852..08489337e 100644 --- a/admin/scons/Setup.py +++ b/admin/scons/Setup.py @@ -74,7 +74,7 @@ def defineBuildEnvironment(): env.Replace( CPPPATH =["#src"] # used to find includes, "#" means always absolute to build-root , CPPDEFINES=['LUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines , CCFLAGS='-Wall -Wextra -Wformat-security' - , CXXFLAGS='-std=gnu++14 -Wno-enum-compare -Wno-noexcept-type' + , CXXFLAGS='-std=gnu++17 -Wno-enum-compare' , CFLAGS='-std=gnu99' ) env.Append(LINKFLAGS='-Wl,--no-undefined') # require every dependency is given on link, in the right order diff --git a/doc/technical/build/BuildDependencies.txt b/doc/technical/build/BuildDependencies.txt index de350c20d..db70c83f7 100644 --- a/doc/technical/build/BuildDependencies.txt +++ b/doc/technical/build/BuildDependencies.txt @@ -1,7 +1,7 @@ Build Dependencies ================== :Author: core-devs -:Date: 11/2015 +:Date: 2/2020 :toc: @@ -54,29 +54,32 @@ Languages and Tools * C / C++ - - a C99 / C++14 compatible compiler footnote:[in practice, we build using GCC and + - a C99 / C++17 compatible compiler footnote:[in practice, we build using GCC and occasionally we check using Clang] - - GCC *4.9* or Clang *3.5* should be fine footnote:[basically we try to use just the stock language. + - GCC *7* or Clang *6* should be fine footnote:[basically we try to use just the stock language. On rare occasions in the past, we _did_ use some GCC extensions, like `typeof()`, but we care for workarounds, in case this becomes a problem. Incidentally, `typeof()` is obsoleted by the new C++ standard, which provides `decltype()` for this purpose.]. * BOOST (listed below are the Debian package names) - - libboost-dev (at least *1.55*) + - libboost-dev (at least *1.67*) - libboost-program-options-dev - libboost-program-options-dev - libboost-filesystem-dev * Script languages - - Python (*2.7*) for build scripts + - Python (*2.x*) might still be handy for build scripts.footnote:[SCons supports both Python 2.x + and Python 3.x transparently. Basically there is no reason to stick to Python 2.x -- just the standard + python is not yet switched on Debian/stable, and so we might miss out on some scripts.] - bash (some test scripts use bash specific extensions) Build Tools ~~~~~~~~~~~ * Git -* SCons *2.0* footnote:[we build with SCons >= 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/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/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/building.txt b/doc/user/tutorials/building.txt index e09f2dcd7..6206894a6 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 @@ -46,7 +46,7 @@ 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/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 03d827485..fd5aa9024 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -44515,8 +44515,8 @@
- - + + @@ -44933,12 +44933,13 @@ - + - + - + + @@ -44973,6 +44974,9 @@ + + + @@ -45237,8 +45241,8 @@ - - + + @@ -45335,8 +45339,8 @@ - - + + @@ -45501,14 +45505,14 @@ - + - - + + - - + + @@ -45594,9 +45598,9 @@ - + - + @@ -45643,7 +45647,7 @@ - + @@ -45654,15 +45658,16 @@ - + - - + + + - + @@ -45675,24 +45680,24 @@ - + - - - - - + + + + + - + - - - + + + @@ -45715,8 +45720,8 @@ - - + + @@ -45739,15 +45744,15 @@ - + - - - + + + - - - + + + @@ -45765,14 +45770,14 @@ - + - + - - + + @@ -45785,31 +45790,31 @@ - + - - + + - + - - + + - + - + - + - + @@ -45828,8 +45833,11 @@ - - + + + + + From 421a2ed49a53385a99b1e514c8b758b71b4fb88d Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 21 Feb 2020 23:55:09 +0100 Subject: [PATCH 16/16] C++17: some related clean-up --- doc/user/tutorials/DebianBuilding.txt | 2 +- doc/user/tutorials/building.txt | 2 +- src/lib/diagnostic-context.hpp | 44 ++--- src/lib/iter-tree-explorer.hpp | 8 +- src/lib/maybe.hpp | 122 ------------ src/lib/multifact.hpp | 10 +- src/lib/thread-local.hpp | 113 ----------- tests/25fundamental.tests | 5 - tests/basics/diagnostic-context-test.cpp | 10 +- .../diff/tree-mutator-binding-test.cpp | 5 + tests/library/maybe-value-test.cpp | 182 ------------------ tests/vault/thread-local-test.cpp | 117 ----------- 12 files changed, 34 insertions(+), 586 deletions(-) delete mode 100644 src/lib/maybe.hpp delete mode 100644 src/lib/thread-local.hpp delete mode 100644 tests/library/maybe-value-test.cpp delete mode 100644 tests/vault/thread-local-test.cpp 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 6206894a6..023bc10fa 100644 --- a/doc/user/tutorials/building.txt +++ b/doc/user/tutorials/building.txt @@ -40,7 +40,7 @@ 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 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/iter-tree-explorer.hpp b/src/lib/iter-tree-explorer.hpp index 4d4918a61..73640a64c 100644 --- a/src/lib/iter-tree-explorer.hpp +++ b/src/lib/iter-tree-explorer.hpp @@ -446,8 +446,7 @@ namespace lib { namespace iter_explorer { // Implementation of Iterator decorating layers... - /*constexpr*/ ///////////////////////////////////////////////////////////TICKET #1138 : lambdas are literal only in C++17 - auto ACCEPT_ALL = [](auto){return true;}; + constexpr auto ACCEPT_ALL = [](auto){return true;}; /** * @internal technical details of binding a functor into the TreeExplorer. @@ -578,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/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/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/tests/25fundamental.tests b/tests/25fundamental.tests index f42fe79cb..74e3d76e8 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/library/diff/tree-mutator-binding-test.cpp b/tests/library/diff/tree-mutator-binding-test.cpp index 8059810b8..c9995658c 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/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/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