From e6c871485740f7e6d2daaa73c35516e83f86811c Mon Sep 17 00:00:00 2001 From: peri4 Date: Wed, 28 Aug 2024 11:56:36 +0300 Subject: [PATCH] version 4.1.0 maybe fix hang on PIEthernet::interrupt() replace piLetobe with piChangeEndian: * piChangeEndianBinary * piChangeBinary * piChangedBinary PIDiagnostics::start now accept PISystemTime instead of number add PITimer::start(PISystemTime, std::function) overload --- CMakeLists.txt | 4 +- libs/main/core/pibase.h | 129 ++++++++++++++++---------- libs/main/core/pimemoryblock.h | 9 +- libs/main/core/piwaitevent_p.cpp | 1 + libs/main/io_utils/pibasetransfer.cpp | 3 +- libs/main/io_utils/pidiagnostics.cpp | 12 +-- libs/main/io_utils/pidiagnostics.h | 2 +- libs/main/thread/pitimer.cpp | 8 ++ libs/main/thread/pitimer.h | 6 +- main.cpp | 5 + 10 files changed, 113 insertions(+), 66 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b05912a2..4b13bc72 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,9 +2,9 @@ cmake_minimum_required(VERSION 3.0) cmake_policy(SET CMP0017 NEW) # need include() with .cmake project(PIP) set(PIP_MAJOR 4) -set(PIP_MINOR 0) +set(PIP_MINOR 1) set(PIP_REVISION 0) -set(PIP_SUFFIX _alpha) +set(PIP_SUFFIX ) set(PIP_COMPANY SHS) set(PIP_DOMAIN org.SHS) diff --git a/libs/main/core/pibase.h b/libs/main/core/pibase.h index c2e94594..f9b7106d 100644 --- a/libs/main/core/pibase.h +++ b/libs/main/core/pibase.h @@ -35,6 +35,7 @@ #define PIBASE_H #include "pibase_macros.h" +#include "pimemoryblock.h" #include "pip_export.h" #include @@ -352,14 +353,6 @@ inline constexpr T piClamp(const T & v, const T & min, const T & max) { return (v > max ? max : (v < min ? min : v)); } -//! \~\brief -//! \~english Function inverse byte order in memory block ([1..N] -> [N..1]) -//! \~russian Метод для смены порядка байт в блоке памяти ([1..N] -> [N..1]) -inline void piLetobe(void * data, int size) { - for (int i = 0; i < size / 2; i++) - piSwap(((uchar *)data)[size - i - 1], ((uchar *)data)[i]); -} - //! \~\brief //! \~english Function for compare two numeric values with epsilon //! \~russian Метод для сравнения двух чисел с порогом @@ -383,66 +376,104 @@ inline bool piCompare(const T & a, const T & b, const T & epsilon = std::numeric return piAbs(a - b) <= epsilon; } + +// Endians + + +//! \~\brief +//! \~english Function inverse byte order in memory block ([1..N] -> [N..1]) +//! \~russian Метод для смены порядка байт в блоке памяти ([1..N] -> [N..1]) +inline void piChangeEndianBinary(void * data, size_t size) { + auto hs = size / 2; + for (size_t i = 0; i < hs; i++) + piSwap(((uchar *)data)[size - i - 1], ((uchar *)data)[i]); +} + +//! \~\brief +//! \~english Function inverse byte order in memory block ([1..N] -> [N..1]) +//! \~russian Метод для смены порядка байт в блоке памяти ([1..N] -> [N..1]) +inline void piChangeEndianBinary(PIMemoryBlock mem_blk) { + if (mem_blk.isNull()) return; + piChangeEndianBinary(mem_blk.data(), mem_blk.size()); +} + + //! \~\brief //! \~english Templated function that inverse byte order of value "v" //! \~russian Шаблонный метод, меняющий порядок байт в переменной "v" template -inline void piLetobe(T * v) { - piLetobe(v, sizeof(T)); -} +inline void piChangeEndian(T & v); + //! \~\brief -//! \~english Templated function that returns "v" with inversed byte order -//! \~russian Шаблонный метод, возвращающий переменную "v" с измененным порядком байт -//! \~\details -//! \~english -//! This function used to convert values between little and big endian \n -//! There are some macros: -//! - \c piLetobes for "ushort" -//! - \c piLetobei for "uint" -//! - \c piLetobel for "ulong" -//! - \c piLetobell for "ullong" -//! -//! Example: -//! \snippet piincludes.cpp letobe -//! \~russian -//! Этот метод используется для изменения порядка байт между little и big endian -//! Есть несколько макросов: -//! - \c piLetobes для "ushort" -//! - \c piLetobei для "uint" -//! - \c piLetobel для "ulong" -//! - \c piLetobell для "ullong" -//! -//! Пример: -//! \snippet piincludes.cpp letobe +//! \~english Templated function that returns value "v" with inversed byte order +//! \~russian Шаблонный метод, возвращающий значение "v" с измененным порядком байт template -inline T piLetobe(const T & v) { - T tv(v); - piLetobe(&tv, sizeof(T)); - return tv; +inline T piChangedEndian(const T & v); + + +template +inline void piChangeEndian(T & v) { + piChangeEndianBinary(&v, sizeof(T)); } -// specialization +template +inline T piChangedEndian(const T & v) { + T ret = v; + piChangeEndianBinary(&ret, sizeof(T)); + return ret; +} template<> -inline uint16_t piLetobe(const uint16_t & v) { +inline uint16_t piChangedEndian(const uint16_t & v) { return (v << 8) | (v >> 8); } template<> -inline uint32_t piLetobe(const uint32_t & v) { +inline uint32_t piChangedEndian(const uint32_t & v) { return (v >> 24) | ((v >> 8) & 0xFF00) | ((v << 8) & 0xFF0000) | ((v << 24) & 0xFF000000); } template<> -inline float piLetobe(const float & v) { - union _pletobe_f { - _pletobe_f(const float & f_) { f = f_; } +inline float piChangedEndian(const float & v) { + union { float f; - uint32_t v; - }; - _pletobe_f a(v); - a.v = (a.v >> 24) | ((a.v >> 8) & 0xFF00) | ((a.v << 8) & 0xFF0000) | ((a.v << 24) & 0xFF000000); - return a.f; + uint32_t i; + } u; + u.f = v; + u.i = piChangedEndian(u.i); + return u.f; } +template<> +inline void piChangeEndian(uint16_t & v) { + v = piChangedEndian(v); +} +template<> +inline void piChangeEndian(uint32_t & v) { + v = piChangedEndian(v); +} +template<> +inline void piChangeEndian(float & v) { + v = piChangedEndian(v); +} + + +DEPRECATEDM("use piChangeEndianBinary()") +inline void piLetobe(void * data, int size) { + piChangeEndianBinary(data, size); +} + +template +DEPRECATEDM("use piChangeEndianBinary()") +inline void piLetobe(T * v) { + piChangeEndianBinary(v, sizeof(T)); +} + +template +DEPRECATEDM("use piChangeEndian() or piChangedEndian()") +inline T piLetobe(const T & v) { + return piChangedEndian(v); +} + + //! \~\brief //! \~english Generic hash function, implements murmur3/32 algorithm //! \~russian Хэш-функция общего назначения, по алгоритму murmur3/32 diff --git a/libs/main/core/pimemoryblock.h b/libs/main/core/pimemoryblock.h index ce3aee60..ad98c4e1 100644 --- a/libs/main/core/pimemoryblock.h +++ b/libs/main/core/pimemoryblock.h @@ -36,10 +36,7 @@ struct PIMemoryBlock { public: //! \~english Constructs data block //! \~russian Создает блок данных - PIMemoryBlock(void * data_ = 0, int size_ = 0) { - d = data_; - s = size_; - } + PIMemoryBlock() {} //! \~english Constructs data block //! \~russian Создает блок данных @@ -71,6 +68,10 @@ public: //! \~russian Размер данных в байтах int size() const { return s; } + //! \~english Returns if this block points to nothing + //! \~russian Возвращает пустой ли указатель на данные + bool isNull() const { return d; } + private: void * d; int s; diff --git a/libs/main/core/piwaitevent_p.cpp b/libs/main/core/piwaitevent_p.cpp index ba2dcbdc..1130ca13 100644 --- a/libs/main/core/piwaitevent_p.cpp +++ b/libs/main/core/piwaitevent_p.cpp @@ -51,6 +51,7 @@ void PIWaitEvent::create() { piCout << "Error with pipe:" << errorString(); } else { fcntl(pipe_fd[ReadEnd], F_SETFL, O_NONBLOCK); + fcntl(pipe_fd[WriteEnd], F_SETFL, O_NONBLOCK); } #endif } diff --git a/libs/main/io_utils/pibasetransfer.cpp b/libs/main/io_utils/pibasetransfer.cpp index f509a44f..3575a284 100644 --- a/libs/main/io_utils/pibasetransfer.cpp +++ b/libs/main/io_utils/pibasetransfer.cpp @@ -19,6 +19,7 @@ #include "pibasetransfer.h" +#include "piliterals_time.h" #include "pitime.h" const uint PIBaseTransfer::signature = 0x54424950; @@ -37,7 +38,7 @@ PIBaseTransfer::PIBaseTransfer(): crc(standardCRC_16()), diag(false) { timeout_ = 10.; diag.setDisconnectTimeout(PISystemTime::fromSeconds(timeout_ / 10.)); diag.setName("PIBaseTransfer"); - diag.start(50); + diag.start(20_Hz); packets_count = 10; #ifdef MICRO_PIP setPacketSize(512); diff --git a/libs/main/io_utils/pidiagnostics.cpp b/libs/main/io_utils/pidiagnostics.cpp index 61a38fb6..9cfe5964 100644 --- a/libs/main/io_utils/pidiagnostics.cpp +++ b/libs/main/io_utils/pidiagnostics.cpp @@ -94,16 +94,14 @@ PIString PIDiagnostics::sendSpeed() const { void PIDiagnostics::start() { - PITimer::start(10_Hz); - changeDisconnectTimeout(disconn_); + PIDiagnostics::start(10_Hz); } -void PIDiagnostics::start(double msecs) { - if (msecs > 0.) { - PITimer::start(PISystemTime::fromMilliseconds(msecs)); - changeDisconnectTimeout(disconn_); - } +void PIDiagnostics::start(PISystemTime interval) { + if (interval.isNull()) return; + PITimer::start(interval); + changeDisconnectTimeout(disconn_); } diff --git a/libs/main/io_utils/pidiagnostics.h b/libs/main/io_utils/pidiagnostics.h index b1a5635d..cc50bd25 100644 --- a/libs/main/io_utils/pidiagnostics.h +++ b/libs/main/io_utils/pidiagnostics.h @@ -96,7 +96,7 @@ public: EVENT_HANDLER0(void, start); - EVENT_HANDLER1(void, start, double, msecs); + EVENT_HANDLER1(void, start, PISystemTime, interval); EVENT_HANDLER0(void, reset); EVENT_HANDLER1(void, received, int, size) { received(size, true); } diff --git a/libs/main/thread/pitimer.cpp b/libs/main/thread/pitimer.cpp index 114e900e..f22aa04b 100644 --- a/libs/main/thread/pitimer.cpp +++ b/libs/main/thread/pitimer.cpp @@ -259,6 +259,14 @@ bool PITimer::start(PISystemTime interval) { } +bool PITimer::start(PISystemTime interval, std::function func) { + if (isRunning()) stopAndWait(); + setInterval(interval); + setSlot(func); + return start(); +} + + void PITimer::stopAndWait(PISystemTime timeout) { stop(); thread->waitForFinish(timeout); diff --git a/libs/main/thread/pitimer.h b/libs/main/thread/pitimer.h index 73ef373c..1f40ac4c 100644 --- a/libs/main/thread/pitimer.h +++ b/libs/main/thread/pitimer.h @@ -73,12 +73,14 @@ public: //! \~russian Ожидает остановки таймера bool waitForFinish(PISystemTime timeout = {}); - //! \fn bool start(PISystemTime interval) - //! \brief //! \~english Start timer with "interval" loop delay //! \~russian Запустить таймер с интервалом "interval" bool start(PISystemTime interval); + //! \~english Start timer with "interval" loop delay and tick function "func" + //! \~russian Запустить таймер с интервалом "interval" и вызываевымым методом "func" + bool start(PISystemTime interval, std::function func); + bool start(double interval_ms) DEPRECATEDM("use start(PISystemTime)") { return start(PISystemTime::fromMilliseconds(interval_ms)); } EVENT_HANDLER0(bool, start); diff --git a/main.cpp b/main.cpp index 66a38948..35c1849d 100644 --- a/main.cpp +++ b/main.cpp @@ -28,6 +28,11 @@ void tfunc4(int delim) { int main(int argc, char * argv[]) { + uint v = 0xaabbccdd; + piCout << Hex << v << piChangedEndian(v); + piChangeEndianBinary(&v, sizeof(v)); + piCout << Hex << v << piChangedEndian(v); + return 0; /*PIPackedTCP * tcp_s = PIIODevice::createFromFullPath("ptcp://s::8000")->cast(); // new PIPackedTCP(PIPackedTCP::Server, {"0.0.0.0:8000"}); PIPackedTCP * tcp_c = PIIODevice::createFromFullPath("ptcp://c:127.0.0.1:8000")