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 % 72 72
Test Date: 2026-10-20 22:20:34 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        3606 : execution_context::
      18            3606 : execution_context()
      19            3606 :     : frame_alloc_(get_recycling_memory_resource())
      20                 : {
      21            3606 : }
      22                 : 
      23            3606 : execution_context::
      24                 : ~execution_context()
      25                 : {
      26                 :     // A service created after a derived destructor destroyed the
      27                 :     // services would be destroyed here, after the derived members it
      28                 :     // may still reach.
      29            3606 :     BOOST_CAPY_ASSERT(!destroyed_ || !head_);
      30            3606 :     shutdown();
      31            3606 :     destroy();
      32            3606 : }
      33                 : 
      34                 : void
      35            7147 : execution_context::
      36                 : shutdown() noexcept
      37                 : {
      38            7147 :     if(shutdown_)
      39            3541 :         return;
      40            3606 :     shutdown_ = true;
      41                 : 
      42            3606 :     service* p = head_;
      43            4689 :     while(p)
      44                 :     {
      45            1083 :         p->shutdown();
      46            1083 :         p = p->next_;
      47                 :     }
      48                 : }
      49                 : 
      50                 : void
      51            6136 : execution_context::
      52                 : destroy() noexcept
      53                 : {
      54                 :     // One at a time, so a destructor can still find the services not
      55                 :     // yet destroyed, and one it creates is destroyed in turn.
      56            7225 :     while(service* p = head_)
      57                 :     {
      58            1089 :         head_ = p->next_;
      59            1089 :         delete p;
      60            1089 :     }
      61            6136 :     destroyed_ = true;
      62            6136 : }
      63                 : 
      64                 : execution_context::service*
      65           13644 : execution_context::
      66                 : find_impl(detail::type_index ti) const noexcept
      67                 : {
      68           13644 :     auto p = head_;
      69           13670 :     while(p)
      70                 :     {
      71           11477 :         if(p->t0_ == ti || p->t1_ == ti)
      72           11451 :             break;
      73              26 :         p = p->next_;
      74                 :     }
      75           13644 :     return p;
      76                 : }
      77                 : 
      78                 : execution_context::service&
      79           12491 : execution_context::
      80                 : use_service_impl(factory& f)
      81                 : {
      82           12491 :     std::unique_lock<std::mutex> lock(mutex_);
      83                 : 
      84           12491 :     if(auto* p = find_impl(f.t0))
      85           11424 :         return *p;
      86                 : 
      87            1067 :     lock.unlock();
      88                 : 
      89                 :     // Create the service outside lock, enabling nested calls
      90            1067 :     service* sp = f.create(*this);
      91            1067 :     sp->t0_ = f.t0;
      92            1067 :     sp->t1_ = f.t1;
      93                 : 
      94            1067 :     lock.lock();
      95                 : 
      96            1067 :     if(auto* p = find_impl(f.t0))
      97                 :     {
      98                 :         delete sp; // LCOV_EXCL_LINE concurrent same-type registration race
      99                 :         return *p; // LCOV_EXCL_LINE concurrent same-type registration race
     100                 :     }
     101                 : 
     102            1065 :     sp->next_ = head_;
     103            1065 :     head_ = sp;
     104                 : 
     105            1065 :     if(shutdown_)
     106                 :     {
     107                 :         // Created after the context shut down: it starts shut down,
     108                 :         // like the services that already were.
     109               3 :         lock.unlock();
     110               3 :         sp->shutdown();
     111                 :     }
     112            1065 :     return *sp;
     113           12491 : }
     114                 : 
     115                 : execution_context::service&
     116              28 : execution_context::
     117                 : make_service_impl(factory& f)
     118                 : {
     119                 :     {
     120              28 :         std::lock_guard<std::mutex> lock(mutex_);
     121              28 :         if(find_impl(f.t0))
     122               2 :             detail::throw_invalid_argument();
     123              26 :         if(f.t0 != f.t1 && find_impl(f.t1))
     124               1 :             detail::throw_invalid_argument();
     125              28 :     }
     126                 : 
     127                 :     // Unlocked to allow nested service creation from constructor
     128              25 :     service* p = f.create(*this);
     129                 : 
     130              25 :     std::unique_lock<std::mutex> lock(mutex_);
     131              25 :     if(find_impl(f.t0))
     132                 :     {
     133                 :         delete p; // LCOV_EXCL_LINE concurrent same-type registration race
     134                 :         detail::throw_invalid_argument(); // LCOV_EXCL_LINE concurrent same-type registration race
     135                 :     }
     136                 : 
     137              25 :     p->t0_ = f.t0;
     138              25 :     if(f.t0 != f.t1)
     139                 :     {
     140               3 :         if(find_impl(f.t1))
     141                 :         {
     142               1 :             delete p;
     143               1 :             detail::throw_invalid_argument();
     144                 :         }
     145               2 :         p->t1_ = f.t1;
     146                 :     }
     147                 :     else
     148                 :     {
     149              22 :         p->t1_ = f.t0;
     150                 :     }
     151                 : 
     152              24 :     p->next_ = head_;
     153              24 :     head_ = p;
     154                 : 
     155              24 :     if(shutdown_)
     156                 :     {
     157                 :         // Created after the context shut down: it starts shut down,
     158                 :         // like the services that already were.
     159               3 :         lock.unlock();
     160               3 :         p->shutdown();
     161                 :     }
     162              24 :     return *p;
     163              25 : }
     164                 : 
     165                 : } // namespace capy
     166                 : } // namespace boost
        

Generated by: LCOV version 2.3