LCOV - code coverage report
Current view: top level - src - threadloop.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 44 59 74.6 %
Date: 2024-11-15 09:04:49 Functions: 8 11 72.7 %

          Line data    Source code
       1             : /*
       2             :  *  Copyright (C) 2004-2024 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             : #include <ciso646> // fix windows compiler bug
      22             : 
      23             : namespace jami {
      24             : 
      25             : void
      26         998 : ThreadLoop::mainloop(std::thread::id& tid,
      27             :                      const std::function<bool()> setup,
      28             :                      const std::function<void()> process,
      29             :                      const std::function<void()> cleanup)
      30             : {
      31         998 :     tid = std::this_thread::get_id();
      32             :     try {
      33         999 :         if (setup()) {
      34   212573168 :             while (state_ == ThreadState::RUNNING)
      35   212568238 :                 process();
      36        1220 :             cleanup();
      37             :         } else {
      38           0 :             JAMI_ERR("setup failed");
      39             :         }
      40           0 :     } catch (const ThreadLoopException& e) {
      41           0 :         JAMI_ERR("[threadloop:%p] ThreadLoopException: %s", this, e.what());
      42           0 :     } catch (const std::exception& e) {
      43           0 :         JAMI_ERR("[threadloop:%p] Unwaited exception: %s", this, e.what());
      44           0 :     }
      45         999 :     stop();
      46         999 : }
      47             : 
      48        1419 : ThreadLoop::ThreadLoop(const std::function<bool()>& setup,
      49             :                        const std::function<void()>& process,
      50        1419 :                        const std::function<void()>& cleanup)
      51        1419 :     : setup_(setup)
      52        1419 :     , process_(process)
      53        1419 :     , cleanup_(cleanup)
      54        2838 :     , thread_()
      55        1419 : {}
      56             : 
      57        1419 : ThreadLoop::~ThreadLoop()
      58             : {
      59        1419 :     if (isRunning()) {
      60           0 :         JAMI_ERR("join() should be explicitly called in owner's destructor");
      61           0 :         join();
      62             :     }
      63        1419 : }
      64             : 
      65             : void
      66        1013 : ThreadLoop::start()
      67             : {
      68        1013 :     const auto s = state_.load();
      69             : 
      70        1013 :     if (s == ThreadState::RUNNING) {
      71          14 :         JAMI_ERR("already started");
      72          14 :         return;
      73             :     }
      74             : 
      75             :     // stop pending but not processed by thread yet?
      76         999 :     if (s == ThreadState::STOPPING and thread_.joinable()) {
      77          14 :         JAMI_DBG("stop pending");
      78          14 :         thread_.join();
      79             :     }
      80             : 
      81         999 :     state_ = ThreadState::RUNNING;
      82         999 :     thread_ = std::thread(&ThreadLoop::mainloop, this, std::ref(threadId_), setup_, process_, cleanup_);
      83         999 :     threadId_ = thread_.get_id();
      84             : }
      85             : 
      86             : void
      87        3262 : ThreadLoop::stop()
      88             : {
      89        3262 :     auto expected = ThreadState::RUNNING;
      90        3262 :     state_.compare_exchange_strong(expected, ThreadState::STOPPING);
      91        3262 : }
      92             : 
      93             : void
      94        1715 : ThreadLoop::join()
      95             : {
      96        1715 :     stop();
      97        1715 :     if (thread_.joinable())
      98         985 :         thread_.join();
      99        1715 : }
     100             : 
     101             : void
     102           0 : ThreadLoop::waitForCompletion()
     103             : {
     104           0 :     if (thread_.joinable())
     105           0 :         thread_.join();
     106           0 : }
     107             : 
     108             : void
     109           0 : ThreadLoop::exit()
     110             : {
     111           0 :     stop();
     112           0 :     throw ThreadLoopException();
     113             : }
     114             : 
     115             : bool
     116       18156 : ThreadLoop::isRunning() const noexcept
     117             : {
     118             : #ifdef _WIN32
     119             :     return state_ == ThreadState::RUNNING;
     120             : #else
     121       18156 :     return thread_.joinable() and state_ == ThreadState::RUNNING;
     122             : #endif
     123             : }
     124             : 
     125             : void
     126        1196 : InterruptedThreadLoop::stop()
     127             : {
     128        1196 :     ThreadLoop::stop();
     129        1196 :     cv_.notify_one();
     130        1196 : }
     131             : } // namespace jami

Generated by: LCOV version 1.14