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