LCOV - code coverage report
Current view: top level - src - threadloop.cpp (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 81.4 % 59 48
Test Date: 2026-07-06 08:25:38 Functions: 60.9 % 23 14

            Line data    Source code
       1              : /*
       2              :  *  Copyright (C) 2004-2026 Savoir-faire Linux Inc.
       3              :  *
       4              :  *  This program is free software: you can redistribute it and/or modify
       5              :  *  it under the terms of the GNU General Public License as published by
       6              :  *  the Free Software Foundation, either version 3 of the License, or
       7              :  *  (at your option) any later version.
       8              :  *
       9              :  *  This program is distributed in the hope that it will be useful,
      10              :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12              :  *  GNU General Public License for more details.
      13              :  *
      14              :  *  You should have received a copy of the GNU General Public License
      15              :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16              :  */
      17              : 
      18              : #include "threadloop.h"
      19              : #include "logger.h"
      20              : 
      21              : namespace jami {
      22              : 
      23              : void
      24         1040 : ThreadLoop::mainloop(std::thread::id& tid,
      25              :                      const std::function<bool()>& setup,
      26              :                      const std::function<void()>& process,
      27              :                      const std::function<void()>& cleanup)
      28              : {
      29         1040 :     tid = std::this_thread::get_id();
      30              :     try {
      31         1040 :         if (setup()) {
      32    202998808 :             while (state_ == ThreadState::RUNNING)
      33    202996712 :                 process();
      34         1030 :             cleanup();
      35              :         } else {
      36            0 :             JAMI_ERROR("setup failed");
      37              :         }
      38            1 :     } catch (const ThreadLoopException& e) {
      39            0 :         JAMI_ERROR("[threadloop:{}] ThreadLoopException: {}", fmt::ptr(this), e.what());
      40            1 :     } catch (const std::exception& e) {
      41            4 :         JAMI_ERROR("[threadloop:{}] Unwaited exception: {}", fmt::ptr(this), e.what());
      42            1 :     }
      43         1040 :     stop();
      44         1040 : }
      45              : 
      46         1451 : ThreadLoop::ThreadLoop(const std::function<bool()>& setup,
      47              :                        const std::function<void()>& process,
      48         1451 :                        const std::function<void()>& cleanup)
      49         1451 :     : setup_(setup)
      50         1451 :     , process_(process)
      51         1451 :     , cleanup_(cleanup)
      52         2902 :     , thread_()
      53         1451 : {}
      54              : 
      55         1451 : ThreadLoop::~ThreadLoop()
      56              : {
      57         1451 :     if (isRunning()) {
      58            0 :         JAMI_ERROR("join() should be explicitly called in owner's destructor");
      59            0 :         join();
      60              :     }
      61         1451 : }
      62              : 
      63              : void
      64         1049 : ThreadLoop::start()
      65              : {
      66         1049 :     const auto s = state_.load();
      67              : 
      68         1050 :     if (s == ThreadState::RUNNING) {
      69           41 :         JAMI_ERROR("already started");
      70           10 :         return;
      71              :     }
      72              : 
      73              :     // stop pending but not processed by thread yet?
      74         1039 :     if (s == ThreadState::STOPPING and thread_.joinable()) {
      75           56 :         JAMI_LOG("stop pending");
      76           14 :         thread_.join();
      77              :     }
      78              : 
      79         1039 :     state_ = ThreadState::RUNNING;
      80         1040 :     thread_ = std::thread(&ThreadLoop::mainloop, this, std::ref(threadId_), setup_, process_, cleanup_);
      81         1040 :     threadId_ = thread_.get_id();
      82              : }
      83              : 
      84              : void
      85         3297 : ThreadLoop::stop()
      86              : {
      87         3297 :     auto expected = ThreadState::RUNNING;
      88         3297 :     state_.compare_exchange_strong(expected, ThreadState::STOPPING);
      89         3296 : }
      90              : 
      91              : void
      92         1738 : ThreadLoop::join()
      93              : {
      94         1738 :     stop();
      95         1738 :     if (thread_.joinable())
      96         1026 :         thread_.join();
      97         1738 : }
      98              : 
      99              : void
     100            0 : ThreadLoop::waitForCompletion()
     101              : {
     102            0 :     if (thread_.joinable())
     103            0 :         thread_.join();
     104            0 : }
     105              : 
     106              : void
     107            0 : ThreadLoop::exit()
     108              : {
     109            0 :     stop();
     110            0 :     throw ThreadLoopException();
     111              : }
     112              : 
     113              : bool
     114        17697 : ThreadLoop::isRunning() const noexcept
     115              : {
     116              : #ifdef _WIN32
     117              :     return state_ == ThreadState::RUNNING;
     118              : #else
     119        17697 :     return thread_.joinable() and state_ == ThreadState::RUNNING;
     120              : #endif
     121              : }
     122              : 
     123              : void
     124         1213 : InterruptedThreadLoop::stop()
     125              : {
     126         1213 :     ThreadLoop::stop();
     127         1213 :     cv_.notify_one();
     128         1213 : }
     129              : } // namespace jami
        

Generated by: LCOV version 2.0-1