LCOV - code coverage report
Current view: top level - foo/src - threadloop.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 42 59 71.2 %
Date: 2026-04-22 10:25:21 Functions: 8 11 72.7 %

          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         362 : 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         362 :     tid = std::this_thread::get_id();
      30             :     try {
      31         363 :         if (setup()) {
      32       15889 :             while (state_ == ThreadState::RUNNING)
      33       15526 :                 process();
      34         363 :             cleanup();
      35             :         } else {
      36           0 :             JAMI_ERR("setup failed");
      37             :         }
      38           0 :     } catch (const ThreadLoopException& e) {
      39           0 :         JAMI_ERR("[threadloop:%p] ThreadLoopException: %s", this, e.what());
      40           0 :     } catch (const std::exception& e) {
      41           0 :         JAMI_ERR("[threadloop:%p] Unwaited exception: %s", this, e.what());
      42           0 :     }
      43         363 :     stop();
      44         363 : }
      45             : 
      46         526 : ThreadLoop::ThreadLoop(const std::function<bool()>& setup,
      47             :                        const std::function<void()>& process,
      48         526 :                        const std::function<void()>& cleanup)
      49         526 :     : setup_(setup)
      50         526 :     , process_(process)
      51         526 :     , cleanup_(cleanup)
      52        1052 :     , thread_()
      53         526 : {}
      54             : 
      55         526 : ThreadLoop::~ThreadLoop()
      56             : {
      57         526 :     if (isRunning()) {
      58           0 :         JAMI_ERR("join() should be explicitly called in owner's destructor");
      59           0 :         join();
      60             :     }
      61         526 : }
      62             : 
      63             : void
      64         368 : ThreadLoop::start()
      65             : {
      66         368 :     const auto s = state_.load();
      67             : 
      68         368 :     if (s == ThreadState::RUNNING) {
      69           5 :         JAMI_ERR("already started");
      70           5 :         return;
      71             :     }
      72             : 
      73             :     // stop pending but not processed by thread yet?
      74         363 :     if (s == ThreadState::STOPPING and thread_.joinable()) {
      75           0 :         JAMI_DBG("stop pending");
      76           0 :         thread_.join();
      77             :     }
      78             : 
      79         363 :     state_ = ThreadState::RUNNING;
      80         363 :     thread_ = std::thread(&ThreadLoop::mainloop, this, std::ref(threadId_), setup_, process_, cleanup_);
      81         363 :     threadId_ = thread_.get_id();
      82             : }
      83             : 
      84             : void
      85        1203 : ThreadLoop::stop()
      86             : {
      87        1203 :     auto expected = ThreadState::RUNNING;
      88        1203 :     state_.compare_exchange_strong(expected, ThreadState::STOPPING);
      89        1202 : }
      90             : 
      91             : void
      92         654 : ThreadLoop::join()
      93             : {
      94         654 :     stop();
      95         654 :     if (thread_.joinable())
      96         363 :         thread_.join();
      97         654 : }
      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        1592 : ThreadLoop::isRunning() const noexcept
     115             : {
     116             : #ifdef _WIN32
     117             :     return state_ == ThreadState::RUNNING;
     118             : #else
     119        1592 :     return thread_.joinable() and state_ == ThreadState::RUNNING;
     120             : #endif
     121             : }
     122             : 
     123             : void
     124         443 : InterruptedThreadLoop::stop()
     125             : {
     126         443 :     ThreadLoop::stop();
     127         443 :     cv_.notify_one();
     128         443 : }
     129             : } // namespace jami

Generated by: LCOV version 1.14