LCOV - code coverage report
Current view: top level - /jenkins/workspace/boost-root/libs/capy/src/ex - execution_context.cpp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 88.6 % 88 78 10
Test Date: 2026-04-01 22:02:47 Functions: 100.0 % 7 7

           TLA  Line data    Source code
       1                 : //
       2                 : // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
       3                 : //
       4                 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5                 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6                 : //
       7                 : // Official repository: https://github.com/cppalliance/capy
       8                 : //
       9                 : 
      10                 : #include <boost/capy/ex/execution_context.hpp>
      11                 : #include <boost/capy/ex/recycling_memory_resource.hpp>
      12                 : #include <boost/capy/detail/except.hpp>
      13                 : 
      14                 : namespace boost {
      15                 : namespace capy {
      16                 : 
      17 HIT        3002 : execution_context::
      18            3002 : execution_context()
      19            3002 :     : frame_alloc_(get_recycling_memory_resource())
      20                 : {
      21            3002 : }
      22                 : 
      23            3002 : execution_context::
      24                 : ~execution_context()
      25                 : {
      26            3002 :     shutdown();
      27            3002 :     destroy();
      28            3002 : }
      29                 : 
      30                 : void
      31            3159 : execution_context::
      32                 : shutdown() noexcept
      33                 : {
      34            3159 :     if(shutdown_)
      35             157 :         return;
      36            3002 :     shutdown_ = true;
      37                 : 
      38            3002 :     service* p = head_;
      39            3065 :     while(p)
      40                 :     {
      41              63 :         p->shutdown();
      42              63 :         p = p->next_;
      43                 :     }
      44                 : }
      45                 : 
      46                 : void
      47            3159 : execution_context::
      48                 : destroy() noexcept
      49                 : {
      50            3159 :     service* p = head_;
      51            3159 :     head_ = nullptr;
      52            3222 :     while(p)
      53                 :     {
      54              63 :         service* next = p->next_;
      55              63 :         delete p;
      56              63 :         p = next;
      57                 :     }
      58          104247 :     for(auto& s : slots_)
      59          101088 :         s.store(nullptr, std::memory_order_relaxed);
      60            3159 : }
      61                 : 
      62                 : execution_context::service*
      63             144 : execution_context::
      64                 : find_impl(detail::type_index ti) const noexcept
      65                 : {
      66             144 :     auto p = head_;
      67             148 :     while(p)
      68                 :     {
      69              10 :         if(p->t0_ == ti || p->t1_ == ti)
      70               6 :             break;
      71               4 :         p = p->next_;
      72                 :     }
      73             144 :     return p;
      74                 : }
      75                 : 
      76                 : execution_context::service&
      77              57 : execution_context::
      78                 : use_service_impl(factory& f)
      79                 : {
      80              57 :     std::unique_lock<std::mutex> lock(mutex_);
      81                 : 
      82              57 :     if(auto* p = find_impl(f.t0))
      83                 :     {
      84 MIS           0 :         if(f.slot0 < max_service_slots)
      85               0 :             slots_[f.slot0].store(p, std::memory_order_release);
      86               0 :         if(f.slot0 != f.slot1 && f.slot1 < max_service_slots)
      87               0 :             slots_[f.slot1].store(p, std::memory_order_release);
      88               0 :         return *p;
      89                 :     }
      90                 : 
      91 HIT          57 :     lock.unlock();
      92                 : 
      93                 :     // Create the service outside lock, enabling nested calls
      94              57 :     service* sp = f.create(*this);
      95              57 :     sp->t0_ = f.t0;
      96              57 :     sp->t1_ = f.t1;
      97                 : 
      98              57 :     lock.lock();
      99                 : 
     100              57 :     if(auto* p = find_impl(f.t0))
     101                 :     {
     102               3 :         if(f.slot0 < max_service_slots)
     103               3 :             slots_[f.slot0].store(p, std::memory_order_release);
     104               3 :         if(f.slot0 != f.slot1 && f.slot1 < max_service_slots)
     105 MIS           0 :             slots_[f.slot1].store(p, std::memory_order_release);
     106 HIT           3 :         delete sp;
     107               3 :         return *p;
     108                 :     }
     109                 : 
     110              54 :     sp->next_ = head_;
     111              54 :     head_ = sp;
     112                 : 
     113              54 :     if(f.slot0 < max_service_slots)
     114              54 :         slots_[f.slot0].store(sp, std::memory_order_release);
     115              54 :     if(f.slot0 != f.slot1 && f.slot1 < max_service_slots)
     116               1 :         slots_[f.slot1].store(sp, std::memory_order_release);
     117                 : 
     118              54 :     return *sp;
     119              57 : }
     120                 : 
     121                 : execution_context::service&
     122              12 : execution_context::
     123                 : make_service_impl(factory& f)
     124                 : {
     125                 :     {
     126              12 :         std::lock_guard<std::mutex> lock(mutex_);
     127              12 :         if(find_impl(f.t0))
     128               2 :             detail::throw_invalid_argument();
     129              10 :         if(f.t0 != f.t1 && find_impl(f.t1))
     130               1 :             detail::throw_invalid_argument();
     131              12 :     }
     132                 : 
     133                 :     // Unlocked to allow nested service creation from constructor
     134               9 :     service* p = f.create(*this);
     135                 : 
     136               9 :     std::lock_guard<std::mutex> lock(mutex_);
     137               9 :     if(find_impl(f.t0))
     138                 :     {
     139 MIS           0 :         delete p;
     140               0 :         detail::throw_invalid_argument();
     141                 :     }
     142                 : 
     143 HIT           9 :     p->t0_ = f.t0;
     144               9 :     if(f.t0 != f.t1)
     145                 :     {
     146               2 :         if(find_impl(f.t1))
     147                 :         {
     148 MIS           0 :             delete p;
     149               0 :             detail::throw_invalid_argument();
     150                 :         }
     151 HIT           2 :         p->t1_ = f.t1;
     152                 :     }
     153                 :     else
     154                 :     {
     155               7 :         p->t1_ = f.t0;
     156                 :     }
     157                 : 
     158               9 :     p->next_ = head_;
     159               9 :     head_ = p;
     160                 : 
     161               9 :     if(f.slot0 < max_service_slots)
     162               9 :         slots_[f.slot0].store(p, std::memory_order_release);
     163               9 :     if(f.slot0 != f.slot1 && f.slot1 < max_service_slots)
     164               2 :         slots_[f.slot1].store(p, std::memory_order_release);
     165                 : 
     166               9 :     return *p;
     167               9 : }
     168                 : 
     169                 : } // namespace capy
     170                 : } // namespace boost
        

Generated by: LCOV version 2.3