From 2e3c462073571e6c3725b3e678616aa8e2bf35ab Mon Sep 17 00:00:00 2001 From: "HARMEL, Bernard" Date: Fri, 26 Jul 2024 11:00:34 +0200 Subject: [PATCH] 5.7.2.1 --- CMakeLists.txt | 2 +- lib/include/bofstd/bofbasicloggerfactory.h | 85 ++++++--- lib/include/bofstd/bofthread.h | 55 +++++- lib/include/bofstd/ibofloggerfactory.h | 52 +++--- lib/src/bofthread.cpp | 83 ++++++++- tests/src/main.cpp | 4 +- tests/src/ut_logger.cpp | 195 +++++++++++---------- tests/src/ut_threading.cpp | 65 ++++--- vcpkg.json | 2 +- 9 files changed, 367 insertions(+), 176 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 759fb66..d5f3c3e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,7 +47,7 @@ include(cmake/fetch_content.cmake) # in code coverage computation as they are test programs themselves. set(EXTRA_COVERAGE_EXCLUSION "\'${CMAKE_CURRENT_SOURCE_DIR}/integration/*\'") -project(bofstd VERSION 5.7.1.5) +project(bofstd VERSION 5.7.2.1) if (EMSCRIPTEN) message("Force pthread detection for BofStd compilation under EMSCRIPTEN") diff --git a/lib/include/bofstd/bofbasicloggerfactory.h b/lib/include/bofstd/bofbasicloggerfactory.h index e70be5c..5782160 100644 --- a/lib/include/bofstd/bofbasicloggerfactory.h +++ b/lib/include/bofstd/bofbasicloggerfactory.h @@ -14,21 +14,22 @@ * V 1.00 Feb 19 2024 BHA : Initial release */ #pragma once +#include #include #include #include #include #include -#include BEGIN_BOF_NAMESPACE() class BasicLogger : public BOF::IBofLogger { public: - BasicLogger(const std::string &_rLibNamePrefix_S, const std::string &_rLoggerChannelName_S) : BOF::IBofLogger() + BasicLogger(const std::string &_rLibNamePrefix_S, const std::string &_rLoggerChannelName_S) + : BOF::IBofLogger() { mChannelName_S = _rLibNamePrefix_S + _rLoggerChannelName_S; - Open(false, false, false, ""); + Open(false, false, false, 0, ""); } virtual ~BasicLogger() { @@ -38,11 +39,12 @@ class BasicLogger : public BOF::IBofLogger mpLogFile_X = nullptr; } } - void V_Log(LogSeverity /*_SeverityLevel_E*/, const char *_pLogMessage_c, ...) override + void V_Log(LogSeverity /*_SeverityLevel_E*/, const std::string &_rFile_S, uint32_t _Line_U32, const std::string &_rFunc_S, const char *_pLogMessage_c, ...) override { if ((mOutputOnScreen_B) || (mpLogFile_X)) { char pHeader_c[0x100], pLog_c[0x1000]; + const char *pFile_c; va_list VaList_X; const auto Now = std::chrono::high_resolution_clock::now(); const std::chrono::duration Delta = Now - mLogEpoch; @@ -57,40 +59,57 @@ class BasicLogger : public BOF::IBofLogger t = std::time(nullptr); std::strftime(pDateTime_c, sizeof(pDateTime_c), "%Y-%m-%d %H:%M:%S", std::localtime(&t)); - sprintf(pHeader_c, "%s: %zd [%s]->", pDateTime_c, DeltaInuS, mChannelName_S.c_str()); + BOF_GET_FILE_FROM_PATH(_rFile_S.c_str(), pFile_c) + sprintf(pHeader_c, "%s: %zd [%s] %s:%d (%s)->", pDateTime_c, DeltaInuS, mChannelName_S.c_str(), pFile_c, _Line_U32, _rFunc_S.c_str()); + mNbLogLine_U32++; if (mOutputOnScreen_B) { printf("%s%s", pHeader_c, pLog_c); } if (mpLogFile_X) { - fwrite(pHeader_c, strlen(pHeader_c), 1, mpLogFile_X); - fwrite(pLog_c, strlen(pLog_c), 1, mpLogFile_X); - if (mAutoFlush_B) + if ((mNbLogLine_U32 & 0x0000000F)==0) + { + if (Size() > mMaxSizeInByte_U32) + { + SwapLogFile(); + } + } + if (mpLogFile_X) { - Flush(); + fwrite(pHeader_c, strlen(pHeader_c), 1, mpLogFile_X); + fwrite(pLog_c, strlen(pLog_c), 1, mpLogFile_X); + if ((mNbLogLine_U32 & 0x0000000F) == 0) + { + if (mAutoFlush_B) + { + Flush(); + } + } } } } } - bool Open(bool _OutputOnScreen_B, bool _Append_B, bool _AutoFlush_B, const std::string &_rLogFileSubDir_S) + bool Open(bool _OutputOnScreen_B, bool _Append_B, bool _AutoFlush_B, uint32_t _MaxSizeInByte_U32, const std::string &_rLogFileSubDir_S) { bool Rts_B = true; - char pLogFile_c[512]; mOutputOnScreen_B = _OutputOnScreen_B; mAutoFlush_B = _AutoFlush_B; + mMaxSizeInByte_U32 = _MaxSizeInByte_U32; + mLogFileSubDir_S = _rLogFileSubDir_S; + mNbLogLine_U32 = 0; //Not really true if append mode but not serious as it is only used to lower call frequency to SwapLogFile check and Flush if (_rLogFileSubDir_S.empty()) { mpLogFile_X = nullptr; } else { - sprintf(pLogFile_c, "%s/%s.log", _rLogFileSubDir_S.c_str(), mChannelName_S.c_str()); - mpLogFile_X = _Append_B ? fopen(pLogFile_c, "w+"): fopen(pLogFile_c, "a+"); + sprintf(mpLogFilePath_c, "%s/%s.log", _rLogFileSubDir_S.c_str(), mChannelName_S.c_str()); + mpLogFile_X = _Append_B ? fopen(mpLogFilePath_c, "w+") : fopen(mpLogFilePath_c, "a+"); if (mpLogFile_X) { - V_Log(LOG_SEVERITY_FORCE, "New log session started...\n"); + V_Log(LOG_SEVERITY_FORCE, __FILE__, __LINE__, __func__, "New log session started...\n"); } else { @@ -105,7 +124,7 @@ class BasicLogger : public BOF::IBofLogger if (mpLogFile_X) { - V_Log(LOG_SEVERITY_FORCE, "Log session finished !\n"); + V_Log(LOG_SEVERITY_FORCE, __FILE__, __LINE__, __func__, "Log session finished !\n"); fclose(mpLogFile_X); mpLogFile_X = nullptr; } @@ -113,17 +132,34 @@ class BasicLogger : public BOF::IBofLogger return Rts_B; } + bool SwapLogFile() + { + bool Rts_B = false; + char pBackLogFilePath_c[1024]; + //if (Close()) //No because never ending loop (Close call V_Log) and modify var mOutputOnScreen_B + if (mpLogFile_X) + { + fclose(mpLogFile_X); + sprintf(pBackLogFilePath_c, "%s.back", mpLogFilePath_c); + Bof_DeleteFile(pBackLogFilePath_c); + if (Bof_RenameFile(mpLogFilePath_c, pBackLogFilePath_c) == BOF_ERR_NO_ERROR) + { + Rts_B = Open(mOutputOnScreen_B, false, mAutoFlush_B, mMaxSizeInByte_U32, mLogFileSubDir_S); + } + } + return Rts_B; + } uint64_t Size() { - uint64_t Rts_U64=0; //CurrentPosition_U64 + uint64_t Rts_U64 = 0, CurrentPosition_U64; if (mpLogFile_X) { - //CurrentPosition_U64 = ftell(mpLogFile_X); - //fseek(mpLogFile_X, 0, SEEK_END); + CurrentPosition_U64 = ftell(mpLogFile_X); + fseek(mpLogFile_X, 0, SEEK_END); Rts_U64 = ftell(mpLogFile_X); - //fseek(mpLogFile_X, CurrentPosition_U64, SEEK_SET); + fseek(mpLogFile_X, CurrentPosition_U64, SEEK_SET); } return Rts_U64; } @@ -137,19 +173,24 @@ class BasicLogger : public BOF::IBofLogger } return Rts_B; } + private: std::string mChannelName_S; const std::chrono::time_point mLogEpoch = std::chrono::high_resolution_clock::now(); bool mOutputOnScreen_B = false; bool mAutoFlush_B = false; FILE *mpLogFile_X = nullptr; + std::string mLogFileSubDir_S; + char mpLogFilePath_c[1024]; + uint32_t mMaxSizeInByte_U32 = 0; + uint32_t mNbLogLine_U32 = 0; }; class BofBasicLoggerFactory : public BOF::IBofLoggerFactory { public: - BofBasicLoggerFactory(bool _OutputOnScreen_B, bool _Append_B, bool _AutoFlush_B, const std::string &_rLogFileSubDir_S) : - mOutputOnScreen_B(_OutputOnScreen_B), mAppend_B(_Append_B), mAutoFlush_B(_AutoFlush_B), mLogFileSubDir_S(_rLogFileSubDir_S) + BofBasicLoggerFactory(bool _OutputOnScreen_B, bool _Append_B, bool _AutoFlush_B, const std::string &_rLogFileSubDir_S) + : mOutputOnScreen_B(_OutputOnScreen_B), mAppend_B(_Append_B), mAutoFlush_B(_AutoFlush_B), mLogFileSubDir_S(_rLogFileSubDir_S) { } virtual ~BofBasicLoggerFactory() = default; @@ -169,7 +210,7 @@ class BofBasicLoggerFactory : public BOF::IBofLoggerFactory psRts = std::make_shared(_rLibNamePrefix_S, _rLoggerChannelName_S); if (psRts) { - if (psRts->Open(mOutputOnScreen_B, mAppend_B, mAutoFlush_B, mLogFileSubDir_S)) + if (psRts->Open(mOutputOnScreen_B, mAppend_B, mAutoFlush_B, (1024*1024), mLogFileSubDir_S)) { ChannelName_S = BuildChannelName(_rLibNamePrefix_S, _rLoggerChannelName_S); mLoggerCollection[ChannelName_S] = psRts; diff --git a/lib/include/bofstd/bofthread.h b/lib/include/bofstd/bofthread.h index 00c6670..c596881 100644 --- a/lib/include/bofstd/bofthread.h +++ b/lib/include/bofstd/bofthread.h @@ -208,7 +208,60 @@ struct BOF_THREAD_POOL_ENTRY FctToExec = nullptr; } }; +#if 1 +struct BOF_THREAD_POOL_PARAM +{ + uint32_t PoolSize_U32; + uint32_t MaxQueuedRequests_U32; + std::string BaseName_S; + bool PriorityInversionAware_B; + BOF::BOF_THREAD_SCHEDULER_POLICY ThreadSchedulerPolicy_E; + BOF::BOF_THREAD_PRIORITY ThreadPriority_E; + uint64_t ThreadCpuCoreAffinityMask_U64; + uint32_t StackSize_U32; + + BOF_THREAD_POOL_PARAM() + { + Reset(); + } + void Reset() + { + PoolSize_U32 = 0; + MaxQueuedRequests_U32 = 0; + BaseName_S = ""; + PriorityInversionAware_B = false; + ThreadSchedulerPolicy_E = BOF::BOF_THREAD_SCHEDULER_POLICY::BOF_THREAD_SCHEDULER_POLICY_MAX; + ThreadPriority_E = BOF::BOF_THREAD_PRIORITY::BOF_THREAD_PRIORITY_000; + ThreadCpuCoreAffinityMask_U64 = 0; + StackSize_U32 = 0; + } +}; +class BofThreadPool +{ +public: + BofThreadPool(const BOF_THREAD_POOL_PARAM &_rThreadPoolParam_X); + BofThreadPool(const BofThreadPool &) = delete; + ~BofThreadPool(); + + bool Enqueue(std::function _Fn, void *_pArg); + +private: + BOFERR OnProcessing(); + + struct THREAD_PARAM + { + std::function Fn; + void *pArg; + }; + BOF_THREAD_POOL_PARAM mThreadPoolParam_X; + std::vector> mThreadCollection; + std::list mJobCollection; + bool mDoShutdown_B = false; + std::condition_variable mDoShedulCv; + std::mutex mMtx; +}; +#else class ThreadPoolExecutor; class BOFSTD_EXPORT BofThreadPool { @@ -234,5 +287,5 @@ class BOFSTD_EXPORT BofThreadPool BOFERR ReleaseDispatch(BOFERR _Sts_E, BOF_THREAD_POOL_ENTRY *_pThreadPoolEntry_X, ThreadPoolExecutor *_pThreadPoolExecutor); //Called internally, do not call this method (ThreadPoolExecutor is internal) }; - +#endif END_BOF_NAMESPACE() \ No newline at end of file diff --git a/lib/include/bofstd/ibofloggerfactory.h b/lib/include/bofstd/ibofloggerfactory.h index 277916b..6451319 100644 --- a/lib/include/bofstd/ibofloggerfactory.h +++ b/lib/include/bofstd/ibofloggerfactory.h @@ -14,10 +14,10 @@ * V 1.00 Feb 19 2024 BHA : Initial release */ #pragma once +#include #include #include #include -#include #include "bofstd/bofstd.h" @@ -38,7 +38,7 @@ class IBofLogger IBofLogger() = default; virtual ~IBofLogger() = default; - virtual void V_Log(LogSeverity _SeverityLevel_E, const char *_pLogMessage_c, ...) = 0; + virtual void V_Log(LogSeverity _SeverityLevel_E, const std::string &_rFile_S, uint32_t _Line_U32, const std::string &_rFunc_S, const char *_pLogMessage_c, ...) = 0; inline bool SetLogSeverityLevel(LogSeverity _SeverityLevel_E) { bool Rts_B = false; @@ -71,33 +71,33 @@ class IBofLoggerFactory virtual bool V_Destroy(const std::string &_rLibNamePrefix_S, const std::string &_rLoggerChannelName_S) = 0; }; -#define LOGGER_LOG(psLogger, level, format, ...) \ - if (psLogger) \ - { \ - if (level <= psLogger->GetLogSeverityLevel()) \ - { \ - psLogger->V_Log(level, format, ##__VA_ARGS__); \ - psLogger->mNbLogOut_U32++; \ - } \ - else \ - { \ - psLogger->mNbLogRejected_U32++; \ - } \ +#define LOGGER_LOG(psLogger, Level, File, Line, Func, Format, ...) \ + if (psLogger) \ + { \ + if (Level <= psLogger->GetLogSeverityLevel()) \ + { \ + psLogger->V_Log(Level, File, Line, Func, Format, ##__VA_ARGS__); \ + psLogger->mNbLogOut_U32++; \ + } \ + else \ + { \ + psLogger->mNbLogRejected_U32++; \ + } \ } #ifdef LOGGER_FACTORY_DISABLE_LOGGING -#define LOG_FORCE(psLogger, format, ...) -#define LOG_ERROR(psLogger, format, ...) -#define LOG_WARNING(psLogger, format, ...) -#define LOG_INFO(psLogger, format, ...) -#define LOG_VERBOSE(psLogger, format, ...) -#define LOG_DEBUG(psLogger, format, ...) +#define LOG_FORCE(psLogger, Format, ...) +#define LOG_ERROR(psLogger, Format, ...) +#define LOG_WARNING(psLogger, Format, ...) +#define LOG_INFO(psLogger, Format, ...) +#define LOG_VERBOSE(psLogger, Format, ...) +#define LOG_DEBUG(psLogger, Format, ...) #else -#define LOG_FORCE(psLogger, format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_FORCE, format, ##__VA_ARGS__) -#define LOG_ERROR(psLogger, format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_ERROR, format, ##__VA_ARGS__) -#define LOG_WARNING(psLogger, format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_WARNING, format, ##__VA_ARGS__) -#define LOG_INFO(psLogger, format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_INFO, format, ##__VA_ARGS__) -#define LOG_VERBOSE(psLogger, format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_VERBOSE, format, ##__VA_ARGS__) -#define LOG_DEBUG(psLogger, format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_DEBUG, format, ##__VA_ARGS__) +#define LOG_FORCE(psLogger, Format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_FORCE, __FILE__, __LINE__, __func__, Format, ##__VA_ARGS__) +#define LOG_ERROR(psLogger, Format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_ERROR, __FILE__, __LINE__, __func__, Format, ##__VA_ARGS__) +#define LOG_WARNING(psLogger, Format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_WARNING, __FILE__, __LINE__, __func__, Format, ##__VA_ARGS__) +#define LOG_INFO(psLogger, Format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_INFO, __FILE__, __LINE__, __func__, Format, ##__VA_ARGS__) +#define LOG_VERBOSE(psLogger, Format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_VERBOSE, __FILE__, __LINE__, __func__, Format, ##__VA_ARGS__) +#define LOG_DEBUG(psLogger, Format, ...) LOGGER_LOG(psLogger, BOF::IBofLogger::LOG_SEVERITY_DEBUG, __FILE__, __LINE__, __func__, Format, ##__VA_ARGS__) #endif END_BOF_NAMESPACE() diff --git a/lib/src/bofthread.cpp b/lib/src/bofthread.cpp index 0a5ec37..03bd5e3 100644 --- a/lib/src/bofthread.cpp +++ b/lib/src/bofthread.cpp @@ -57,9 +57,9 @@ typedef struct tagTHREADNAME_INFO BEGIN_BOF_NAMESPACE() std::atomic BofThread::S_mBofThreadBalance = 0; -BofThread::BofThread(): BofThread(false) +BofThread::BofThread() + : BofThread(false) { - } BofThread::BofThread(bool _PriorityInversionAware_B) { @@ -79,7 +79,7 @@ BOFERR BofThread::InitializeThread(const std::string &_rName_S, bool _PriorityIn mThreadErrorCode_E = Bof_CreateMutex(_rName_S + "_mtx", false, false, mThreadMtx_X); if (mThreadErrorCode_E == BOF_ERR_NO_ERROR) { - mThreadErrorCode_E = Bof_CreateEvent(_rName_S + "_wakeup_evt", false, 1, false, false, _PriorityInversionAware_B,mWakeUpEvent_X); + mThreadErrorCode_E = Bof_CreateEvent(_rName_S + "_wakeup_evt", false, 1, false, false, _PriorityInversionAware_B, mWakeUpEvent_X); if (mThreadErrorCode_E == BOF_ERR_NO_ERROR) { mThreadErrorCode_E = Bof_CreateEvent(_rName_S + "_enter_evt", false, 1, true, false, _PriorityInversionAware_B, mThreadEnterEvent_X); @@ -789,7 +789,7 @@ void BofThread::BofThread_Thread() uint32_t Delta_U32; S_mBofThreadBalance++; - //printf("%u: Start of thread '%s' BAL %d this %p\n", Bof_GetMsTickCount(), mThreadParam_X.Name_S.c_str(), S_mBofThreadBalance.load(), this); + // printf("%u: Start of thread '%s' BAL %d this %p\n", Bof_GetMsTickCount(), mThreadParam_X.Name_S.c_str(), S_mBofThreadBalance.load(), this); Sts_E = Bof_SignalEvent(mThreadEnterEvent_X, 0); // printf("%u: ENTER THREAD SIGNAL MTHREADENTEREVENT_X %d\n", BOF::Bof_GetMsTickCount(), Sts_E); BOF_ASSERT(Sts_E == BOF_ERR_NO_ERROR); @@ -904,14 +904,85 @@ void BofThread::BofThread_Thread() Sts_E = Bof_SignalEvent(mThreadExitEvent_X, 0); S_mBofThreadBalance--; // Bof_ErrorCode can fail does to app shudown (static initializer) - //printf("%u: BofThread_Thread End of thread '%s' BAL %d, ExitCode %d MustStop %d\n", Bof_GetMsTickCount(), mThreadParam_X.Name_S.c_str(), S_mBofThreadBalance.load(), Sts_E, mThreadMustStop_B.load()); + // printf("%u: BofThread_Thread End of thread '%s' BAL %d, ExitCode %d MustStop %d\n", Bof_GetMsTickCount(), mThreadParam_X.Name_S.c_str(), S_mBofThreadBalance.load(), Sts_E, mThreadMustStop_B.load()); // BOF_ASSERT(Sts_E == BOF_ERR_NO_ERROR); } int BofThread::S_BofThreadBalance() { return S_mBofThreadBalance.load(); } +#if 1 +BofThreadPool::BofThreadPool(const BOF_THREAD_POOL_PARAM &_rThreadPoolParam_X) +{ + uint32_t i_U32; + mThreadPoolParam_X = _rThreadPoolParam_X; + for (i_U32 = 0; i_U32 < mThreadPoolParam_X.PoolSize_U32; i_U32++) + { + std::unique_ptr puThread = std::make_unique(); + puThread->SetThreadCallback(nullptr, BOF_BIND_0_ARG_TO_METHOD(this, BofThreadPool::OnProcessing), nullptr); + puThread->LaunchBofProcessingThread(mThreadPoolParam_X.BaseName_S + "_" + std::to_string(i_U32), mThreadPoolParam_X.PriorityInversionAware_B, false, 0, + mThreadPoolParam_X.ThreadSchedulerPolicy_E, mThreadPoolParam_X.ThreadPriority_E, + mThreadPoolParam_X.ThreadCpuCoreAffinityMask_U64, 1000, mThreadPoolParam_X.StackSize_U32); + mThreadCollection.emplace_back(std::move(puThread)); + } +} + +BofThreadPool::~BofThreadPool() +{ + // Stop all worker threads... + { + std::unique_lock Lock(mMtx); + mDoShutdown_B = true; + } + mDoShedulCv.notify_all(); + // Join... + for (auto &puThread : mThreadCollection) + { + puThread.reset(nullptr); + } +} +bool BofThreadPool::Enqueue(std::function _Fn, void *_pArg) +{ + bool Rts_B = false; + THREAD_PARAM ThreadParam_X; + { + ThreadParam_X.Fn = _Fn; + ThreadParam_X.pArg = _pArg; + std::unique_lock Lock(mMtx); + if ((mThreadPoolParam_X.MaxQueuedRequests_U32 == 0) || (mJobCollection.size() < mThreadPoolParam_X.MaxQueuedRequests_U32)) + { + mJobCollection.push_back(ThreadParam_X); + Rts_B = true; + } + } + mDoShedulCv.notify_one(); + return Rts_B; +} + +BOFERR BofThreadPool::OnProcessing() +{ + BOFERR Rts_E = BOF_ERR_NO_ERROR; + + while (1) + { + THREAD_PARAM ThreadParam_X; + { + std::unique_lock Lock(mMtx); + mDoShedulCv.wait(Lock, [&] { return ((!mJobCollection.empty()) || (mDoShutdown_B)); }); + if ((mDoShutdown_B) && (mJobCollection.empty())) + { + break; + } + ThreadParam_X = mJobCollection.front(); + mJobCollection.pop_front(); + } + // assert(true == static_cast(Fn)); + ThreadParam_X.Fn(ThreadParam_X.pArg); + } + return Rts_E; +} +#else class ThreadPoolExecutor { public: @@ -1187,5 +1258,5 @@ BOFERR BofThreadPool::ReleaseDispatch(BOFERR _Sts_E, BOF_THREAD_POOL_ENTRY *_pTh BOF_SAFE_DELETE(_pThreadPoolExecutor); return Rts_E; } - +#endif END_BOF_NAMESPACE() \ No newline at end of file diff --git a/tests/src/main.cpp b/tests/src/main.cpp index 76861dd..0c04529 100644 --- a/tests/src/main.cpp +++ b/tests/src/main.cpp @@ -137,8 +137,8 @@ int main(int argc, char *argv[]) // ::testing::GTEST_FLAG(filter) = "ut_logger_ibofloggerfactory.*"; //::testing::GTEST_FLAG(filter) = "RawCircularBuffer_Test.FillWrapOverwrite"; //::testing::GTEST_FLAG(filter) = "RawCircularBuffer_Test.*:CircularBuffer_Test.*:RawCircularBufferInSlotMode_Test.*"; - //::testing::GTEST_FLAG(filter) = "BofThreadPool_Test.*:BofThread_Test.*"; - //::testing::GTEST_FLAG(filter) = "Graph_Test.*:ScopedGuard_Test.*"; + //::testing::GTEST_FLAG(filter) = "BofThreadPool_Test.Dispatch"; + //::testing::GTEST_FLAG(filter) = "ut_logger_ibofloggerfactory.MultipleChannel*"; // ::testing::GTEST_FLAG(filter) = "RawCircularBufferAlwaysContiguous_Test.*:RawCircularBuffer_Test.*:RawCircularBufferInSlotMode_Test.*"; // std::string CrtDir_S; // BOF::Bof_GetCurrentDirectory(CrtDir_S); diff --git a/tests/src/ut_logger.cpp b/tests/src/ut_logger.cpp index 234b444..7030246 100644 --- a/tests/src/ut_logger.cpp +++ b/tests/src/ut_logger.cpp @@ -278,102 +278,7 @@ TEST_F(Logger_Test, LoggerInit) } - //*** External lib code ********************************************************************* - // Logger Channel Definition -enum UT_LOGGER_CHANNEL : uint32_t -{ - UT_LOGGER_CHANNEL_INIT = 0, - UT_LOGGER_CHANNEL_CODEC, - UT_LOGGER_CHANNEL_NULLPTR, - UT_LOGGER_CHANNEL_DMA, - UT_LOGGER_CHANNEL_MAX -}; -static std::array, UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_MAX> S_psLoggerCollection; - -void MyLibInit(std::shared_ptr _psLoggerFactory) -{ - for (auto &rpsLogger : S_psLoggerCollection) - { - rpsLogger = nullptr; - } - if (_psLoggerFactory) - { - S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT] = _psLoggerFactory->V_Create("MyLib_", "INIT"); - S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC] = _psLoggerFactory->V_Create("MyLib_", "CODEC"); - S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_NULLPTR] = nullptr; - S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA] = _psLoggerFactory->V_Create("MyLib_", "DMA"); - } -} -void MyLibCode(bool _NullTestCase_B) -{ - LOG_FORCE(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT], "This will be logged\n"); - LOG_FORCE(S_psLoggerCollection[UT_LOGGER_CHANNEL_CODEC], "This will be logged\n"); - LOG_FORCE(S_psLoggerCollection[UT_LOGGER_CHANNEL_NULLPTR], "! This will not be logged !\n"); - LOG_VERBOSE(S_psLoggerCollection[UT_LOGGER_CHANNEL_DMA], "! This will not be logged !\n"); - LOG_FORCE(S_psLoggerCollection[UT_LOGGER_CHANNEL_DMA], "! This one yes !\n"); - LOG_INFO(S_psLoggerCollection[UT_LOGGER_CHANNEL_DMA], "! This one also !\n"); - if (!_NullTestCase_B) - { - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT]->mNbLogOut_U32, 1); - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT]->mNbLogRejected_U32, 0); - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_CODEC]->mNbLogOut_U32, 1); - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_CODEC]->mNbLogRejected_U32, 0); - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_DMA]->mNbLogOut_U32, 2); - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_DMA]->mNbLogRejected_U32, 1); - } - LOG_INFO(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT], "! This will not be logged !\n"); - LOG_WARNING(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT], "This will be logged\n"); - LOG_ERROR(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT], "This will be logged\n"); - if (!_NullTestCase_B) - { - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT]->mNbLogOut_U32, 3); - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT]->mNbLogRejected_U32, 1); - } -} - -TEST(ut_logger_ibofloggerfactory, MultipleChannel) -{ - std::shared_ptr psLoggerFactory = std::make_shared(true,false,false, "."); - MyLibInit(psLoggerFactory); - EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT] != nullptr); - EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC] != nullptr); - EXPECT_FALSE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_NULLPTR] != nullptr); - EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA] != nullptr); - - EXPECT_TRUE(psLoggerFactory->V_Create("MyLib_", "DMA") == nullptr); - EXPECT_TRUE(psLoggerFactory->V_Create("MyLib_", "DMA2") != nullptr); - EXPECT_TRUE(psLoggerFactory->V_Destroy("MyLib_", "DMA2")); - EXPECT_FALSE(psLoggerFactory->V_Destroy("MyLib_", "DMA3")); - - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_MAX); - EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT]->SetLogSeverityLevel(BOF::IBofLogger::LogSeverity::LOG_SEVERITY_WARNING)); - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_WARNING); - - EXPECT_FALSE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT]->SetLogSeverityLevel(BOF::IBofLogger::LogSeverity::LOG_SEVERITY_MAX)); - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_WARNING); - - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_MAX); - EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC]->SetLogSeverityLevel(BOF::IBofLogger::LogSeverity::LOG_SEVERITY_FORCE)); - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_FORCE); - - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_MAX); - EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA]->SetLogSeverityLevel(BOF::IBofLogger::LogSeverity::LOG_SEVERITY_INFO)); - EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_INFO); - - MyLibCode(false); -} - -TEST(ut_logger_ibofloggerfactory, nullptr) -{ - MyLibInit(nullptr); - EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT] == nullptr); - EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC] == nullptr); - EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_NULLPTR] == nullptr); - EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA] == nullptr); - - MyLibCode(true); -} #if 0 TEST_F(Logger_Test, LoggerFile) @@ -638,4 +543,102 @@ TEST_F(Logger_Test, LoggerMultiChannel) } rBofLog.ShutdownLogger(); } -#endif \ No newline at end of file +#endif + + +//*** External lib code ********************************************************************* + +// Logger Channel Definition +enum UT_LOGGER_CHANNEL : uint32_t +{ + UT_LOGGER_CHANNEL_INIT = 0, + UT_LOGGER_CHANNEL_CODEC, + UT_LOGGER_CHANNEL_NULLPTR, + UT_LOGGER_CHANNEL_DMA, + UT_LOGGER_CHANNEL_MAX +}; +static std::array, UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_MAX> S_psLoggerCollection; + +void MyLibInit(std::shared_ptr _psLoggerFactory) +{ + for (auto &rpsLogger : S_psLoggerCollection) + { + rpsLogger = nullptr; + } + if (_psLoggerFactory) + { + S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT] = _psLoggerFactory->V_Create("MyLib_", "INIT"); + S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC] = _psLoggerFactory->V_Create("MyLib_", "CODEC"); + S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_NULLPTR] = nullptr; + S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA] = _psLoggerFactory->V_Create("MyLib_", "DMA"); + } +} +void MyLibCode(bool _NullTestCase_B) +{ + LOG_FORCE(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT], "This will be logged\n"); + LOG_FORCE(S_psLoggerCollection[UT_LOGGER_CHANNEL_CODEC], "This will be logged\n"); + LOG_FORCE(S_psLoggerCollection[UT_LOGGER_CHANNEL_NULLPTR], "! This will not be logged !\n"); + LOG_VERBOSE(S_psLoggerCollection[UT_LOGGER_CHANNEL_DMA], "! This will not be logged !\n"); + LOG_FORCE(S_psLoggerCollection[UT_LOGGER_CHANNEL_DMA], "! This one yes !\n"); + LOG_INFO(S_psLoggerCollection[UT_LOGGER_CHANNEL_DMA], "! This one also !\n"); + if (!_NullTestCase_B) + { + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT]->mNbLogOut_U32, 1); + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT]->mNbLogRejected_U32, 0); + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_CODEC]->mNbLogOut_U32, 1); + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_CODEC]->mNbLogRejected_U32, 0); + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_DMA]->mNbLogOut_U32, 2); + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_DMA]->mNbLogRejected_U32, 1); + } + LOG_INFO(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT], "! This will not be logged !\n"); + LOG_WARNING(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT], "This will be logged\n"); + LOG_ERROR(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT], "This will be logged\n"); + if (!_NullTestCase_B) + { + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT]->mNbLogOut_U32, 3); + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL_INIT]->mNbLogRejected_U32, 1); + } +} + +TEST(ut_logger_ibofloggerfactory, MultipleChannel) +{ + std::shared_ptr psLoggerFactory = std::make_shared(true, false, false, "."); + MyLibInit(psLoggerFactory); + EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT] != nullptr); + EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC] != nullptr); + EXPECT_FALSE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_NULLPTR] != nullptr); + EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA] != nullptr); + + EXPECT_TRUE(psLoggerFactory->V_Create("MyLib_", "DMA") == nullptr); + EXPECT_TRUE(psLoggerFactory->V_Create("MyLib_", "DMA2") != nullptr); + EXPECT_TRUE(psLoggerFactory->V_Destroy("MyLib_", "DMA2")); + EXPECT_FALSE(psLoggerFactory->V_Destroy("MyLib_", "DMA3")); + + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_MAX); + EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT]->SetLogSeverityLevel(BOF::IBofLogger::LogSeverity::LOG_SEVERITY_WARNING)); + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_WARNING); + + EXPECT_FALSE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT]->SetLogSeverityLevel(BOF::IBofLogger::LogSeverity::LOG_SEVERITY_MAX)); + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_WARNING); + + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_MAX); + EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC]->SetLogSeverityLevel(BOF::IBofLogger::LogSeverity::LOG_SEVERITY_FORCE)); + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_FORCE); + + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_MAX); + EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA]->SetLogSeverityLevel(BOF::IBofLogger::LogSeverity::LOG_SEVERITY_INFO)); + EXPECT_EQ(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA]->GetLogSeverityLevel(), BOF::IBofLogger::LogSeverity::LOG_SEVERITY_INFO); + + MyLibCode(false); +} + +TEST(ut_logger_ibofloggerfactory, nullptr) +{ + MyLibInit(nullptr); + EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_INIT] == nullptr); + EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_CODEC] == nullptr); + EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_NULLPTR] == nullptr); + EXPECT_TRUE(S_psLoggerCollection[UT_LOGGER_CHANNEL::UT_LOGGER_CHANNEL_DMA] == nullptr); + + MyLibCode(true); +} \ No newline at end of file diff --git a/tests/src/ut_threading.cpp b/tests/src/ut_threading.cpp index 04a81c6..8a4f2a3 100644 --- a/tests/src/ut_threading.cpp +++ b/tests/src/ut_threading.cpp @@ -25,28 +25,51 @@ #include USE_BOF_NAMESPACE() -/* -TEST(BofThreadPool_Test, Constructor) -{ - BOF_THREAD_PARAM ThreadParam_X; - ThreadParam_X.Name_S = "ThreadPoolErrUt"; - ThreadParam_X.SignalEvent_B = false; - ThreadParam_X.StackSize_U32 = 0; - ThreadParam_X.StartStopTimeoutInMs_U32 = 2000; - ThreadParam_X.ThreadCpuCoreAffinityMask_U64 = 0; - ThreadParam_X.ThreadPriority_E = BOF_THREAD_PRIORITY::BOF_THREAD_PRIORITY_000; - ThreadParam_X.ThreadSchedulerPolicy_E = BOF_THREAD_SCHEDULER_POLICY::BOF_THREAD_SCHEDULER_POLICY_OTHER; - ThreadParam_X.WakeUpIntervalInMs_U32 = 1000;//!!!! no, see below !!!! - BofThreadPool PoolErr(8, ThreadParam_X); - EXPECT_NE(PoolErr.InitThreadPoolErrorCode(), BOF_ERR_NO_ERROR); - - ThreadParam_X.Name_S = "ThreadPoolUt"; - ThreadParam_X.WakeUpIntervalInMs_U32 = 0;//!!!! important !!!! - BofThreadPool Pool(8, ThreadParam_X); - EXPECT_EQ(Pool.InitThreadPoolErrorCode(), BOF_ERR_NO_ERROR); +#if 1 +static bool S_pDispatchDone_B[16]; +void PoolDispatch(void *_pArg) +{ + uint64_t Id_U64 = (uint64_t)_pArg; + uint32_t SleepTime_U32 = 500 + (Id_U64 * 100); + printf("%u: PoolDispatch[%zu] starts for %d ms...\n", BOF::Bof_GetMsTickCount(), Id_U64, SleepTime_U32); + BOF::Bof_MsSleep(SleepTime_U32); + printf("%u: PoolDispatch[%zu] ends.\n", BOF::Bof_GetMsTickCount(), Id_U64); + S_pDispatchDone_B[Id_U64] = true; } -*/ +TEST(BofThreadPool_Test, Dispatch) +{ + BOF_THREAD_POOL_PARAM ThreadPoolParam_X; + std::unique_ptr puThreadPool; + uint64_t i_U64; + + ThreadPoolParam_X.PoolSize_U32 = 8; + ThreadPoolParam_X.MaxQueuedRequests_U32 = (ThreadPoolParam_X.PoolSize_U32 / 2); + ThreadPoolParam_X.BaseName_S = "BofThreadPool_Test"; + ThreadPoolParam_X.PriorityInversionAware_B = false; + ThreadPoolParam_X.ThreadSchedulerPolicy_E = BOF::BOF_THREAD_SCHEDULER_POLICY::BOF_THREAD_SCHEDULER_POLICY_OTHER; + ThreadPoolParam_X.ThreadPriority_E = BOF::BOF_THREAD_PRIORITY::BOF_THREAD_PRIORITY_000; + ThreadPoolParam_X.ThreadCpuCoreAffinityMask_U64 = 0; + ThreadPoolParam_X.StackSize_U32 = 0; + puThreadPool = std::make_unique(ThreadPoolParam_X); + EXPECT_TRUE(puThreadPool!=nullptr); + for (i_U64 = 0; i_U64 < ThreadPoolParam_X.MaxQueuedRequests_U32; i_U64++) + { + S_pDispatchDone_B[i_U64] = false; + EXPECT_TRUE(puThreadPool->Enqueue(PoolDispatch, (void *)i_U64)); + } + EXPECT_FALSE(puThreadPool->Enqueue(PoolDispatch, (void *)i_U64)); + for (i_U64 = 0; i_U64 < ThreadPoolParam_X.MaxQueuedRequests_U32; i_U64++) + { + while (S_pDispatchDone_B[i_U64] == false) + { + printf("Wait end of processing of thread %zu...\n", i_U64); + Bof_MsSleep(100); + } + } +} +#else + BOFERR PoolDispatch1() { printf("%u: PoolDispatch1 starts for 1000 ms...\n", BOF::Bof_GetMsTickCount()); @@ -215,7 +238,7 @@ TEST(BofThreadPool_Test, Dispatch) } while (pDispatchTicket == nullptr); } } - +#endif class BofThread_Test : public ::testing::Test { public: diff --git a/vcpkg.json b/vcpkg.json index 150354c..910991d 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,6 +1,6 @@ { "name": "bofstd", - "version": "5.7.1.5", + "version": "5.7.2.1", "description": "The onbings general purpose C++ Multiplatform library", "dependencies": [ {