Line data Source code
1 : //
2 : // Copyright (c) 2022 Vinnie Falco (vinnie dot falco at gmail dot 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/beast2
8 : //
9 :
10 : #include <boost/capy/application.hpp>
11 : #include <boost/capy/detail/except.hpp>
12 : #include <boost/assert.hpp>
13 : #include <mutex>
14 : #include <vector>
15 :
16 : namespace boost {
17 : namespace capy {
18 :
19 : enum application::state : char
20 : {
21 : none,
22 : starting,
23 : running,
24 : stopping,
25 : stopped
26 : };
27 :
28 : struct application::impl
29 : {
30 : std::mutex m;
31 : state st = state::none;
32 : };
33 :
34 1 : application::
35 : ~application()
36 : {
37 : {
38 1 : std::lock_guard<std::mutex> lock(impl_->m);
39 1 : if( impl_->st != state::stopped &&
40 1 : impl_->st != state::none)
41 : {
42 : // stop() hasn't returned yet
43 0 : detail::throw_invalid_argument();
44 : }
45 1 : }
46 1 : delete impl_;
47 1 : }
48 :
49 1 : application::
50 1 : application()
51 1 : : impl_(new impl)
52 : {
53 1 : }
54 :
55 : void
56 0 : application::
57 : start()
58 : {
59 : struct action
60 : {
61 0 : action(application& self)
62 0 : : self_(self)
63 : {
64 : std::lock_guard<
65 0 : std::mutex> lock(self_.impl_->m);
66 : // can't call twice
67 0 : if(self_.impl_->st != state::none)
68 0 : detail::throw_invalid_argument();
69 0 : self_.impl_->st = state::starting;
70 0 : }
71 :
72 0 : ~action()
73 0 : {
74 0 : if(n_ == 0)
75 0 : return;
76 : {
77 : std::lock_guard<
78 0 : std::mutex> lock(self_.impl_->m);
79 0 : BOOST_ASSERT(
80 : self_.impl_->st == state::stopping);
81 0 : self_.impl_->st = state::stopping;
82 0 : }
83 : // stop what we started
84 0 : auto v = self_.get_elements();
85 0 : while(n_-- > 0)
86 0 : v[n_].stop();
87 : {
88 : std::lock_guard<std::mutex> lock(
89 0 : self_.impl_->m);
90 0 : self_.impl_->st = state::stopped;
91 0 : }
92 0 : }
93 :
94 0 : void apply()
95 : {
96 0 : auto v = self_.get_elements();
97 0 : while(n_ < v.size())
98 : {
99 0 : v[n_].start();
100 0 : ++n_;
101 : }
102 0 : n_ = 0;
103 : std::lock_guard<
104 0 : std::mutex> lock(self_.impl_->m);
105 0 : self_.impl_->st = state::running;
106 0 : }
107 :
108 : private:
109 : application& self_;
110 : std::size_t n_ = 0;
111 : };
112 :
113 0 : action(*this).apply();
114 0 : }
115 :
116 : void
117 0 : application::
118 : stop()
119 : {
120 : {
121 0 : std::lock_guard<std::mutex> lock(impl_->m);
122 0 : if(impl_->st != state::running)
123 0 : detail::throw_invalid_argument();
124 0 : impl_->st = state::stopping;
125 0 : }
126 :
127 0 : auto v = get_elements();
128 0 : for(std::size_t i = v.size(); i--;)
129 0 : v[i].stop();
130 :
131 : {
132 0 : std::lock_guard<std::mutex> lock(impl_->m);
133 0 : impl_->st = state::stopped;
134 0 : }
135 0 : }
136 :
137 : } // capy
138 : } // boost
|