LCOV - code coverage report
Current view: top level - /jenkins/workspace/boost-root/libs/capy/src/ex - execution_context.cpp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 70 70
Test Date: 2026-10-17 14:10:44 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        3630 : execution_context::
      18            3630 : execution_context()
      19            3630 :     : frame_alloc_(get_recycling_memory_resource())
      20                 : {
      21            3630 : }
      22                 : 
      23            3630 : execution_context::
      24                 : ~execution_context()
      25                 : {
      26            3630 :     shutdown();
      27            3630 :     destroy();
      28            3630 : }
      29                 : 
      30                 : void
      31            7195 : execution_context::
      32                 : shutdown() noexcept
      33                 : {
      34            7195 :     if(shutdown_)
      35            3565 :         return;
      36            3630 :     shutdown_ = true;
      37                 : 
      38            3630 :     service* p = head_;
      39            4710 :     while(p)
      40                 :     {
      41            1080 :         p->shutdown();
      42            1080 :         p = p->next_;
      43                 :     }
      44                 : }
      45                 : 
      46                 : void
      47            6192 : execution_context::
      48                 : destroy() noexcept
      49                 : {
      50                 :     // One at a time, so a destructor can still find the services not
      51                 :     // yet destroyed, and one it creates is destroyed in turn.
      52            7278 :     while(service* p = head_)
      53                 :     {
      54            1086 :         head_ = p->next_;
      55            1086 :         delete p;
      56            1086 :     }
      57            6192 : }
      58                 : 
      59                 : execution_context::service*
      60           13636 : execution_context::
      61                 : find_impl(detail::type_index ti) const noexcept
      62                 : {
      63           13636 :     auto p = head_;
      64           13650 :     while(p)
      65                 :     {
      66           11465 :         if(p->t0_ == ti || p->t1_ == ti)
      67           11451 :             break;
      68              14 :         p = p->next_;
      69                 :     }
      70           13636 :     return p;
      71                 : }
      72                 : 
      73                 : execution_context::service&
      74           12490 : execution_context::
      75                 : use_service_impl(factory& f)
      76                 : {
      77           12490 :     std::unique_lock<std::mutex> lock(mutex_);
      78                 : 
      79           12490 :     if(auto* p = find_impl(f.t0))
      80           11426 :         return *p;
      81                 : 
      82            1064 :     lock.unlock();
      83                 : 
      84                 :     // Create the service outside lock, enabling nested calls
      85            1064 :     service* sp = f.create(*this);
      86            1064 :     sp->t0_ = f.t0;
      87            1064 :     sp->t1_ = f.t1;
      88                 : 
      89            1064 :     lock.lock();
      90                 : 
      91            1064 :     if(auto* p = find_impl(f.t0))
      92                 :     {
      93                 :         delete sp; // LCOV_EXCL_LINE concurrent same-type registration race
      94                 :         return *p; // LCOV_EXCL_LINE concurrent same-type registration race
      95                 :     }
      96                 : 
      97            1064 :     sp->next_ = head_;
      98            1064 :     head_ = sp;
      99                 : 
     100            1064 :     if(shutdown_)
     101                 :     {
     102                 :         // Created after the context shut down: it starts shut down,
     103                 :         // like the services that already were.
     104               3 :         lock.unlock();
     105               3 :         sp->shutdown();
     106                 :     }
     107            1064 :     return *sp;
     108           12490 : }
     109                 : 
     110                 : execution_context::service&
     111              26 : execution_context::
     112                 : make_service_impl(factory& f)
     113                 : {
     114                 :     {
     115              26 :         std::lock_guard<std::mutex> lock(mutex_);
     116              26 :         if(find_impl(f.t0))
     117               2 :             detail::throw_invalid_argument();
     118              24 :         if(f.t0 != f.t1 && find_impl(f.t1))
     119               1 :             detail::throw_invalid_argument();
     120              26 :     }
     121                 : 
     122                 :     // Unlocked to allow nested service creation from constructor
     123              23 :     service* p = f.create(*this);
     124                 : 
     125              23 :     std::unique_lock<std::mutex> lock(mutex_);
     126              23 :     if(find_impl(f.t0))
     127                 :     {
     128                 :         delete p; // LCOV_EXCL_LINE concurrent same-type registration race
     129                 :         detail::throw_invalid_argument(); // LCOV_EXCL_LINE concurrent same-type registration race
     130                 :     }
     131                 : 
     132              23 :     p->t0_ = f.t0;
     133              23 :     if(f.t0 != f.t1)
     134                 :     {
     135               3 :         if(find_impl(f.t1))
     136                 :         {
     137               1 :             delete p;
     138               1 :             detail::throw_invalid_argument();
     139                 :         }
     140               2 :         p->t1_ = f.t1;
     141                 :     }
     142                 :     else
     143                 :     {
     144              20 :         p->t1_ = f.t0;
     145                 :     }
     146                 : 
     147              22 :     p->next_ = head_;
     148              22 :     head_ = p;
     149                 : 
     150              22 :     if(shutdown_)
     151                 :     {
     152                 :         // Created after the context shut down: it starts shut down,
     153                 :         // like the services that already were.
     154               3 :         lock.unlock();
     155               3 :         p->shutdown();
     156                 :     }
     157              22 :     return *p;
     158              23 : }
     159                 : 
     160                 : } // namespace capy
     161                 : } // namespace boost
        

Generated by: LCOV version 2.3