diff --git a/src/lib/thread.cpp b/src/lib/thread.cpp new file mode 100644 index 000000000..588c9d402 --- /dev/null +++ b/src/lib/thread.cpp @@ -0,0 +1,114 @@ +/* + THREAD.hpp - thin convenience wrapper for starting threads + + Copyright (C) Lumiera.org + 2023, 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 sync.cpp + ** This compilation unit holds some implementation details + ** of the [thread wrapper](\ref lib::Thread), relegated here + ** to reduce header inclusions. + ** @warning setting the thread name only works on some POSIX systems, + ** and using a GNU specific addition to the libC here. + */ + + +#include "lib/thread.hpp" +#include "lib/format-string.hpp" +#include "lib/util.hpp" + +#include +#include + +using std::chrono::steady_clock; +using std::chrono_literals::operator ""ms; + + + +namespace lib { +namespace thread{ + + namespace { + + void + setThreadName (std::thread& handle, string name) + { + // API limitation: max 15 characters + \0 + name = util::sanitise(name).substr(0, 15); + + pthread_t nativeHandle = handle.native_handle(); + pthread_setname_np(nativeHandle, name.c_str()); + } + + void + lifecycle (string format, string threadID) + { + string message = util::_Fmt{format} % threadID; + TRACE (thread, "%s", message.c_str()); + } + } + + + + template + void + ThreadWrapper::markThreadStart (string const& threadID) + { + lifecycle ("Thread '%s' start...", threadID); + setThreadName (threadImpl_, threadID); + } + + + template + void + ThreadWrapper::markThreadEnd (string const& threadID) + { + lifecycle ("Thread '%s' finished.", threadID); + } + + + template + void + ThreadWrapper::waitGracePeriod() noexcept + { + try { + auto start = steady_clock::now(); + while (threadImpl_.joinable() + and steady_clock::now () - start < 20ms + ) + std::this_thread::yield(); + } + ERROR_LOG_AND_IGNORE (thread, "Thread shutdown wait") + + if (threadImpl_.joinable()) + ALERT (thread, "Thread failed to terminate after grace period. Abort."); + // invocation of std::thread dtor will presumably call std::terminate... + } + + + template void ThreadWrapper::markThreadStart (string const&); + template void ThreadWrapper::markThreadEnd (string const&); + template void ThreadWrapper::waitGracePeriod () noexcept; + + template void ThreadWrapper::markThreadStart (string const&); + template void ThreadWrapper::markThreadEnd (string const&); + template void ThreadWrapper::waitGracePeriod () noexcept; + + +}}// namespace lib::thread diff --git a/src/lib/thread.hpp b/src/lib/thread.hpp index 69deb4b94..c402867dd 100644 --- a/src/lib/thread.hpp +++ b/src/lib/thread.hpp @@ -105,13 +105,10 @@ #include "lib/nocopy.hpp" #include "include/logging.h" #include "lib/meta/function.hpp" -#include "lib/format-string.hpp" ///////////////////////////OOO RLY? or maybe into CPP file? -#include "lib/result.hpp" #include #include #include -#include namespace lib { @@ -198,40 +195,9 @@ namespace lib { } // Note: implies get_id() != std::thread::id{} ==> it is running private: - void - markThreadStart (string const& threadID) - { - string logMsg = util::_Fmt{"Thread '%s' start..."} % threadID; - TRACE (thread, "%s", logMsg.c_str()); - //////////////////////////////////////////////////////////////////////OOO maybe set the the Thread-ID via POSIX ?? - } - - void - markThreadEnd (string const& threadID) - { - string logMsg = util::_Fmt{"Thread '%s' finished..."} % threadID; - TRACE (thread, "%s", logMsg.c_str()); - } - - void - waitGracePeriod() noexcept - { - using std::chrono::steady_clock; - using std::chrono_literals::operator ""ms; - - try { - auto start = steady_clock::now(); - while (threadImpl_.joinable() - and steady_clock::now () - start < 20ms - ) - std::this_thread::yield(); - } - ERROR_LOG_AND_IGNORE (thread, "Thread shutdown wait") - - if (threadImpl_.joinable()) - ALERT (thread, "Thread failed to terminate after grace period. Abort."); - // invocation of std::thread dtor will presumably call std::terminate... - } + void markThreadStart (string const& threadID); + void markThreadEnd (string const& threadID); + void waitGracePeriod() noexcept; }; }//(End)base implementation. @@ -281,7 +247,7 @@ namespace lib { join () { if (not threadImpl_.joinable()) - throw error::Logic ("joining on an already terminated thread"); + throw lumiera::error::Logic ("joining on an already terminated thread"); threadImpl_.join(); } diff --git a/tests/15library.tests b/tests/15library.tests index ddc1815b6..0757347c8 100644 --- a/tests/15library.tests +++ b/tests/15library.tests @@ -747,17 +747,6 @@ END TEST "util: sanitised identifier" UtilSanitizedIdentifier_test < 'Word' -out-lit: 'a Sentence' --> 'a_Sentence' -out-lit: 'trailing Withespace -out-lit: ' --> 'trailing_Withespace' -out-lit: 'with a lot -out-lit: of Whitespace' --> 'with_a_lot_of_Whitespace' -out-lit: '@with".'much (\$punctuation)[]!' --> '@with.much_(\$punctuation)' -out-lit: '§&Ω%€ leading garbage' --> 'leading_garbage' -out-lit: 'mixed Ω garbage' --> 'mixed_garbage' -out-lit: 'Bääääh!!' --> 'Bh' -out-lit: '§&Ω%€' --> '' return: 0 END diff --git a/tests/library/util-sanitised-identifier-test.cpp b/tests/library/util-sanitised-identifier-test.cpp index bf8288715..bc27f07c7 100644 --- a/tests/library/util-sanitised-identifier-test.cpp +++ b/tests/library/util-sanitised-identifier-test.cpp @@ -26,6 +26,7 @@ #include "lib/test/run.hpp" +#include "lib/test/test-helper.hpp" #include "lib/util.hpp" @@ -42,22 +43,16 @@ namespace test { { virtual void run (Arg) { - print_clean ("Word"); - print_clean ("a Sentence"); - print_clean ("trailing Withespace\n \t"); - print_clean ("with a \t lot\n of Whitespace"); - print_clean ("@with\".\'much ($punctuation)[]!"); - print_clean ("§&Ω%€ leading garbage"); - print_clean ("mixed Ω garbage"); - print_clean ("Bääääh!!"); - print_clean ("§&Ω%€"); + CHECK (sanitise ( "Word") == "Word"_expect); + CHECK (sanitise ( "a Sentence") == "a_Sentence"_expect); + CHECK (sanitise ( "trailing Withespace\n \t") == "trailing_Withespace"_expect); + CHECK (sanitise ("with a \t lot\n of Whitespace") == "with_a_lot_of_Whitespace"_expect); + CHECK (sanitise ( "@with\".\'much ($punctuation)[]!") == "@with.much_($punctuation)"_expect); + CHECK (sanitise ( "§&Ω%€ leading garbage") == "leading_garbage"_expect); + CHECK (sanitise ( "mixed Ω garbage") == "mixed_garbage"_expect); + CHECK (sanitise ( "Bääääh!!") == "Bh"_expect); + CHECK (sanitise ( "§&Ω%€") == ""_expect); } - - /** @test print the original and the sanitised string */ - void print_clean (const string org) - { - cout << "'" << org << "' --> '" << sanitise(org) << "'\n"; - } }; LAUNCHER (UtilSanitizedIdentifier_test, "unit common"); diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index a990804fa..3f36033b3 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -79299,9 +79299,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + @@ -79312,10 +79312,41 @@ Date:   Thu Apr 20 18:53:17 2023 +0200

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

+ std::thread::native_handle() ⟼ liefert hier pthread_t +

+ +
+
+ + + + + + + +