LCOV - code coverage report
Current view: top level - utilities/src - ReusableThread.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 56.5 % 46 26
Test Date: 2025-12-21 13:07:08 Functions: 60.0 % 5 3

            Line data    Source code
       1              : /**
       2              :  * @file ReusableThread.cpp Reusable thread wrapper
       3              :  * The same thread instance can be used with different tasks to be executed
       4              :  * Inspired by:
       5              :  * https://codereview.stackexchange.com/questions/134214/reuseable-c11-thread
       6              :  *
       7              :  * This is part of the DUNE DAQ , copyright 2020.
       8              :  * Licensing/copyright details are in the COPYING file that you should have
       9              :  * received with this code.
      10              :  */
      11              : 
      12              : #include "utilities/ReusableThread.hpp"
      13              : #include "utilities/Issues.hpp"
      14              : 
      15              : #include <string>
      16              : 
      17          374 : dunedaq::utilities::ReusableThread::ReusableThread(int threadid)
      18          374 :   : m_thread_id(threadid)
      19          374 :   , m_task_executed(true)
      20          374 :   , m_task_assigned(false)
      21          374 :   , m_thread_quit(false)
      22          374 :   , m_worker_done(false)
      23          374 :   , m_thread(&ReusableThread::thread_worker, this)
      24              : {
      25          374 : }
      26              : 
      27          374 : dunedaq::utilities::ReusableThread::~ReusableThread()
      28              : {
      29          374 :   while (m_task_assigned) {
      30            0 :     std::this_thread::sleep_for(std::chrono::milliseconds(1));
      31              :   }
      32          374 :   m_thread_quit = true;
      33         1495 :   while (!m_worker_done) {
      34          747 :     std::this_thread::sleep_for(std::chrono::milliseconds(1));
      35          747 :     m_cv.notify_all();
      36              :   }
      37          374 :   m_thread.join();
      38          374 : }
      39              : 
      40              : void
      41            0 : dunedaq::utilities::ReusableThread::set_name(const std::string& name, int tid)
      42              : {
      43            0 :   set_thread_id(tid);
      44            0 :   char tname[16];                                  // NOLINT
      45            0 :   snprintf(tname, 16, "%s-%d", name.c_str(), tid); // NOLINT
      46            0 :   auto handle = m_thread.native_handle();
      47            0 :   pthread_setname_np(handle, tname);
      48              : 
      49            0 :   m_named = true;
      50            0 : }
      51              : 
      52              : void
      53            0 : dunedaq::utilities::ReusableThread::set_pin(int cpuid)
      54              : {
      55              :   // Require that the thread has been named
      56            0 :   if (!m_named) {
      57            0 :     ers::warning(ThreadingIssue(ERS_HERE, "May not set CPU affinity for un-named thread"));
      58              :   }
      59              : 
      60            0 :   auto handle = m_thread.native_handle();
      61            0 :   cpu_set_t cpuset;
      62            0 :   CPU_ZERO(&cpuset);
      63            0 :   CPU_SET(cpuid, &cpuset);
      64            0 :   int rc = pthread_setaffinity_np(handle, sizeof(cpu_set_t), &cpuset);
      65              : 
      66            0 :   if (rc != 0) {
      67            0 :     ers::warning(ThreadingIssue(ERS_HERE, "Error calling pthread_setaffinity_np: " + std::to_string(rc)));
      68              :   }
      69            0 : }
      70              : 
      71              : void
      72          374 : dunedaq::utilities::ReusableThread::thread_worker()
      73              : {
      74          374 :   std::unique_lock<std::mutex> lock(m_mtx);
      75              : 
      76          748 :   while (!m_thread_quit) {
      77          374 :     if (!m_task_executed && m_task_assigned) {
      78            1 :       m_task();
      79            1 :       m_task_executed = true;
      80            1 :       m_task_assigned = false;
      81              :     } else {
      82          373 :       m_cv.wait(lock);
      83              :     }
      84              :   }
      85              : 
      86          374 :   m_worker_done = true;
      87          374 : }
        

Generated by: LCOV version 2.0-1