91.43% Lines (64/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   3010 execution_context:: 17   3010 execution_context::
HITCBC 18   3010 execution_context() 18   3010 execution_context()
HITCBC 19   3010 : frame_alloc_(get_recycling_memory_resource()) 19   3010 : frame_alloc_(get_recycling_memory_resource())
20   { 20   {
HITCBC 21   3010 } 21   3010 }
22   22  
HITCBC 23   3010 execution_context:: 23   3010 execution_context::
24   ~execution_context() 24   ~execution_context()
25   { 25   {
HITCBC 26   3010 shutdown(); 26   3010 shutdown();
HITCBC 27   3010 destroy(); 27   3010 destroy();
HITCBC 28   3010 } 28   3010 }
29   29  
30   void 30   void
HITCBC 31   3176 execution_context:: 31   3176 execution_context::
32   shutdown() noexcept 32   shutdown() noexcept
33   { 33   {
HITCBC 34   3176 if(shutdown_) 34   3176 if(shutdown_)
HITCBC 35   166 return; 35   166 return;
HITCBC 36   3010 shutdown_ = true; 36   3010 shutdown_ = true;
37   37  
HITCBC 38   3010 service* p = head_; 38   3010 service* p = head_;
HITCBC 39   3076 while(p) 39   3076 while(p)
40   { 40   {
HITCBC 41   66 p->shutdown(); 41   66 p->shutdown();
HITCBC 42   66 p = p->next_; 42   66 p = p->next_;
43   } 43   }
44   } 44   }
45   45  
46   void 46   void
HITCBC 47   3176 execution_context:: 47   3176 execution_context::
48   destroy() noexcept 48   destroy() noexcept
49   { 49   {
HITCBC 50   3176 service* p = head_; 50   3176 service* p = head_;
HITCBC 51   3176 head_ = nullptr; 51   3176 head_ = nullptr;
HITCBC 52   3242 while(p) 52   3242 while(p)
53   { 53   {
HITCBC 54   66 service* next = p->next_; 54   66 service* next = p->next_;
HITCBC 55   66 delete p; 55   66 delete p;
HITCBC 56   66 p = next; 56   66 p = next;
57   } 57   }
HITCBC 58   3176 } 58   3176 }
59   59  
60   execution_context::service* 60   execution_context::service*
HITCBC 61   11593 execution_context:: 61   11593 execution_context::
62   find_impl(detail::type_index ti) const noexcept 62   find_impl(detail::type_index ti) const noexcept
63   { 63   {
HITCBC 64   11593 auto p = head_; 64   11593 auto p = head_;
HITCBC 65   11600 while(p) 65   11600 while(p)
66   { 66   {
HITCBC 67   11461 if(p->t0_ == ti || p->t1_ == ti) 67   11461 if(p->t0_ == ti || p->t1_ == ti)
HITCBC 68   11454 break; 68   11454 break;
HITCBC 69   7 p = p->next_; 69   7 p = p->next_;
70   } 70   }
HITCBC 71   11593 return p; 71   11593 return p;
72   } 72   }
73   73  
74   execution_context::service& 74   execution_context::service&
HITCBC 75   11491 execution_context:: 75   11491 execution_context::
76   use_service_impl(factory& f) 76   use_service_impl(factory& f)
77   { 77   {
HITCBC 78   11491 std::unique_lock<std::mutex> lock(mutex_); 78   11491 std::unique_lock<std::mutex> lock(mutex_);
79   79  
HITCBC 80   11491 if(auto* p = find_impl(f.t0)) 80   11491 if(auto* p = find_impl(f.t0))
HITCBC 81   11432 return *p; 81   11432 return *p;
82   82  
HITCBC 83   59 lock.unlock(); 83   59 lock.unlock();
84   84  
85   // Create the service outside lock, enabling nested calls 85   // Create the service outside lock, enabling nested calls
HITCBC 86   59 service* sp = f.create(*this); 86   59 service* sp = f.create(*this);
HITCBC 87   59 sp->t0_ = f.t0; 87   59 sp->t0_ = f.t0;
HITCBC 88   59 sp->t1_ = f.t1; 88   59 sp->t1_ = f.t1;
89   89  
HITCBC 90   59 lock.lock(); 90   59 lock.lock();
91   91  
HITCBC 92   59 if(auto* p = find_impl(f.t0)) 92   59 if(auto* p = find_impl(f.t0))
93   { 93   {
MISUBC 94   delete sp; 94   delete sp;
MISUBC 95   return *p; 95   return *p;
96   } 96   }
97   97  
HITCBC 98   59 sp->next_ = head_; 98   59 sp->next_ = head_;
HITCBC 99   59 head_ = sp; 99   59 head_ = sp;
100   100  
HITCBC 101   59 return *sp; 101   59 return *sp;
HITCBC 102   11491 } 102   11491 }
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