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

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

Generated by: LCOV version 1.14