94.29% Lines (66/70) 100.00% Functions (7/7)
TLA Baseline Branch
Line Hits Code Line Hits Code
1   // 1   //
2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com) 2   // Copyright (c) 2025 Vinnie Falco (vinnie.falco@gmail.com)
3   // 3   //
4   // Distributed under the Boost Software License, Version 1.0. (See accompanying 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) 5   // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6   // 6   //
7   // Official repository: https://github.com/cppalliance/capy 7   // Official repository: https://github.com/cppalliance/capy
8   // 8   //
9   9  
10   #include <boost/capy/ex/execution_context.hpp> 10   #include <boost/capy/ex/execution_context.hpp>
11   #include <boost/capy/ex/recycling_memory_resource.hpp> 11   #include <boost/capy/ex/recycling_memory_resource.hpp>
12   #include <boost/capy/detail/except.hpp> 12   #include <boost/capy/detail/except.hpp>
13   13  
14   namespace boost { 14   namespace boost {
15   namespace capy { 15   namespace capy {
16   16  
HITCBC 17   2998 execution_context:: 17   3002 execution_context::
HITCBC 18   2998 execution_context() 18   3002 execution_context()
HITCBC 19   2998 : frame_alloc_(get_recycling_memory_resource()) 19   3002 : frame_alloc_(get_recycling_memory_resource())
20   { 20   {
HITCBC 21   2998 } 21   3002 }
22   22  
HITCBC 23   2998 execution_context:: 23   3002 execution_context::
24   ~execution_context() 24   ~execution_context()
25   { 25   {
HITCBC 26   2998 shutdown(); 26   3002 shutdown();
HITCBC 27   2998 destroy(); 27   3002 destroy();
HITCBC 28   2998 } 28   3002 }
29   29  
30   void 30   void
HITCBC 31   3155 execution_context:: 31   3160 execution_context::
32   shutdown() noexcept 32   shutdown() noexcept
33   { 33   {
HITCBC 34   3155 if(shutdown_) 34   3160 if(shutdown_)
HITCBC 35   157 return; 35   158 return;
HITCBC 36   2998 shutdown_ = true; 36   3002 shutdown_ = true;
37   37  
HITCBC 38   2998 service* p = head_; 38   3002 service* p = head_;
HITCBC 39   3057 while(p) 39   3063 while(p)
40   { 40   {
HITCBC 41   59 p->shutdown(); 41   61 p->shutdown();
HITCBC 42   59 p = p->next_; 42   61 p = p->next_;
43   } 43   }
44   } 44   }
45   45  
46   void 46   void
HITCBC 47   3155 execution_context:: 47   3160 execution_context::
48   destroy() noexcept 48   destroy() noexcept
49   { 49   {
HITCBC 50   3155 service* p = head_; 50   3160 service* p = head_;
HITCBC 51   3155 head_ = nullptr; 51   3160 head_ = nullptr;
HITCBC 52   3214 while(p) 52   3221 while(p)
53   { 53   {
HITCBC 54   59 service* next = p->next_; 54   61 service* next = p->next_;
HITCBC 55   59 delete p; 55   61 delete p;
HITCBC 56   59 p = next; 56   61 p = next;
57   } 57   }
HITCBC 58   3155 } 58   3160 }
59   59  
60   execution_context::service* 60   execution_context::service*
HITCBC 61   171 execution_context:: 61   177 execution_context::
62   find_impl(detail::type_index ti) const noexcept 62   find_impl(detail::type_index ti) const noexcept
63   { 63   {
HITCBC 64   171 auto p = head_; 64   177 auto p = head_;
HITCBC 65   178 while(p) 65   184 while(p)
66   { 66   {
HITCBC 67   53 if(p->t0_ == ti || p->t1_ == ti) 67   53 if(p->t0_ == ti || p->t1_ == ti)
HITCBC 68   46 break; 68   46 break;
HITCBC 69   7 p = p->next_; 69   7 p = p->next_;
70   } 70   }
HITCBC 71   171 return p; 71   177 return p;
72   } 72   }
73   73  
74   execution_context::service& 74   execution_context::service&
HITCBC 75   76 execution_context:: 75   78 execution_context::
76   use_service_impl(factory& f) 76   use_service_impl(factory& f)
77   { 77   {
HITCBC 78   76 std::unique_lock<std::mutex> lock(mutex_); 78   78 std::unique_lock<std::mutex> lock(mutex_);
79   79  
HITCBC 80   76 if(auto* p = find_impl(f.t0)) 80   78 if(auto* p = find_impl(f.t0))
HITCBC 81   24 return *p; 81   22 return *p;
82   82  
HITCBC 83   52 lock.unlock(); 83   56 lock.unlock();
84   84  
85   // Create the service outside lock, enabling nested calls 85   // Create the service outside lock, enabling nested calls
HITCBC 86   52 service* sp = f.create(*this); 86   56 service* sp = f.create(*this);
HITCBC 87   52 sp->t0_ = f.t0; 87   56 sp->t0_ = f.t0;
HITCBC 88   52 sp->t1_ = f.t1; 88   56 sp->t1_ = f.t1;
89   89  
HITCBC 90   52 lock.lock(); 90   56 lock.lock();
91   91  
HITCBC 92   52 if(auto* p = find_impl(f.t0)) 92   56 if(auto* p = find_impl(f.t0))
93   { 93   {
HITGBC 94   delete sp; 94   2 delete sp;
HITGBC 95   return *p; 95   2 return *p;
96   } 96   }
97   97  
HITCBC 98   52 sp->next_ = head_; 98   54 sp->next_ = head_;
HITCBC 99   52 head_ = sp; 99   54 head_ = sp;
100   100  
HITCBC 101   52 return *sp; 101   54 return *sp;
HITCBC 102   76 } 102   78 }
103   103  
104   execution_context::service& 104   execution_context::service&
HITCBC 105   10 execution_context:: 105   10 execution_context::
106   make_service_impl(factory& f) 106   make_service_impl(factory& f)
107   { 107   {
108   { 108   {
HITCBC 109   10 std::lock_guard<std::mutex> lock(mutex_); 109   10 std::lock_guard<std::mutex> lock(mutex_);
HITCBC 110   10 if(find_impl(f.t0)) 110   10 if(find_impl(f.t0))
HITCBC 111   2 detail::throw_invalid_argument(); 111   2 detail::throw_invalid_argument();
HITCBC 112   8 if(f.t0 != f.t1 && find_impl(f.t1)) 112   8 if(f.t0 != f.t1 && find_impl(f.t1))
HITCBC 113   1 detail::throw_invalid_argument(); 113   1 detail::throw_invalid_argument();
HITCBC 114   10 } 114   10 }
115   115  
116   // Unlocked to allow nested service creation from constructor 116   // Unlocked to allow nested service creation from constructor
HITCBC 117   7 service* p = f.create(*this); 117   7 service* p = f.create(*this);
118   118  
HITCBC 119   7 std::lock_guard<std::mutex> lock(mutex_); 119   7 std::lock_guard<std::mutex> lock(mutex_);
HITCBC 120   7 if(find_impl(f.t0)) 120   7 if(find_impl(f.t0))
121   { 121   {
MISUBC 122   delete p; 122   delete p;
MISUBC 123   detail::throw_invalid_argument(); 123   detail::throw_invalid_argument();
124   } 124   }
125   125  
HITCBC 126   7 p->t0_ = f.t0; 126   7 p->t0_ = f.t0;
HITCBC 127   7 if(f.t0 != f.t1) 127   7 if(f.t0 != f.t1)
128   { 128   {
HITCBC 129   1 if(find_impl(f.t1)) 129   1 if(find_impl(f.t1))
130   { 130   {
MISUBC 131   delete p; 131   delete p;
MISUBC 132   detail::throw_invalid_argument(); 132   detail::throw_invalid_argument();
133   } 133   }
HITCBC 134   1 p->t1_ = f.t1; 134   1 p->t1_ = f.t1;
135   } 135   }
136   else 136   else
137   { 137   {
HITCBC 138   6 p->t1_ = f.t0; 138   6 p->t1_ = f.t0;
139   } 139   }
140   140  
HITCBC 141   7 p->next_ = head_; 141   7 p->next_ = head_;
HITCBC 142   7 head_ = p; 142   7 head_ = p;
143   143  
HITCBC 144   7 return *p; 144   7 return *p;
HITCBC 145   7 } 145   7 }
146   146  
147   } // namespace capy 147   } // namespace capy
148   } // namespace boost 148   } // namespace boost