neoGFX
Cross-platform C++ app/game engine
lifetime.inl
Go to the documentation of this file.
1 // lifetime.inl
2 /*
3  * Copyright (c) 2019 Leigh Johnston.
4  *
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are
9  * met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  *
14  * * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * * Neither the name of Leigh Johnston nor the names of any
19  * other contributors to this software may be used to endorse or
20  * promote products derived from this software without specific prior
21  * written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35 
36 #pragma once
37 
38 #include <neolib/neolib.hpp>
39 #include <iostream>
40 #include <unordered_set>
41 #include <unordered_map>
42 #include <mutex>
43 #include <atomic>
44 #include <optional>
45 
46 #include <neolib/vecarray.hpp>
47 #include <neolib/null_mutex.hpp>
48 #include <neolib/allocator.hpp>
49 #include <neolib/i_lifetime.hpp>
50 
51 namespace neolib
52 {
53  template <lifetime_state RequiredState, typename Owner>
54  inline lifetime_flag<RequiredState, Owner>::lifetime_flag(const i_lifetime& aSubject, owner_pointer aOwner) :
55  iCookie{ invalid_cookie<cookie_type> }, iSubject { &aSubject }, iOwner{ aOwner }, iState{ aSubject.object_state() }, iDebug{ false }
56  {
57  iCookie = subject().add_flag(*this);
58  }
59 
60  template <lifetime_state RequiredState, typename Owner>
62  iCookie{ invalid_cookie<cookie_type> }, iSubject{ aOther.iSubject }, iOwner{ aOther.iOwner }, iState { aOther.iSubject->object_state() }, iDebug{ false }
63  {
64  iCookie = subject().add_flag(*this);
65  }
66 
67  template <lifetime_state RequiredState, typename Owner>
69  {
70  if (!is_destroyed())
71  subject().remove_flag(*this);
72  }
73 
74  template <lifetime_state RequiredState, typename Owner>
76  {
77  return iCookie;
78  }
79 
80  template <lifetime_state RequiredState, typename Owner>
82  {
83  return iState == lifetime_state::Creating;
84  }
85 
86  template <lifetime_state RequiredState, typename Owner>
88  {
89  return iState == lifetime_state::Alive;
90  }
91 
92  template <lifetime_state RequiredState, typename Owner>
94  {
95  return iState == lifetime_state::Destroying;
96  }
97 
98  template <lifetime_state RequiredState, typename Owner>
100  {
101  return iState == lifetime_state::Destroyed;
102  }
103 
104  template <lifetime_state RequiredState, typename Owner>
106  {
107  return iState == RequiredState;
108  }
109 
110  template <lifetime_state RequiredState, typename Owner>
112  {
113  if (iState == lifetime_state::Alive)
114  return;
115  if (debug())
116  std::cerr << "lifetime_flag::set_alive()" << std::endl;
117  iState = lifetime_state::Alive;
118  }
119 
120  template <lifetime_state RequiredState, typename Owner>
122  {
123  if (iState == lifetime_state::Destroying)
124  return;
125  if (debug())
126  std::cerr << "lifetime_flag::set_destroying()" << std::endl;
127  iState = lifetime_state::Destroying;
128  }
129 
130  template <lifetime_state RequiredState, typename Owner>
132  {
133  if (iState == lifetime_state::Destroyed)
134  return;
135  if (debug())
136  std::cerr << "lifetime_flag::set_destroyed()" << std::endl;
137  iState = lifetime_state::Destroyed;
138  }
139 
140  template <lifetime_state RequiredState, typename Owner>
142  {
143  return iDebug;
144  }
145 
146  template <lifetime_state RequiredState, typename Owner>
148  {
149  iDebug = aDebug;
150  }
151 
152  template <lifetime_state RequiredState, typename Owner>
154  {
155  return *iSubject;
156  }
157 
158  template <typename FlagList>
160  {
161  }
162 
163  template <typename FlagList>
165  {
166  std::scoped_lock<mutex_type> lk(iFlagList.mutex());
167  if (!is_destroyed())
168  {
169  set_destroying();
170  set_destroyed();
171  }
172  }
173 
174  template <typename FlagList>
176  {
177  return iState;
178  }
179 
180  template <typename FlagList>
182  {
183  return iState == lifetime_state::Creating;
184  }
185 
186  template <typename FlagList>
188  {
189  return iState == lifetime_state::Alive;
190  }
191 
192  template <typename FlagList>
194  {
195  return iState == lifetime_state::Destroying;
196  }
197 
198  template <typename FlagList>
200  {
201  return iState == lifetime_state::Destroyed;
202  }
203 
204  template <typename FlagList>
206  {
207  std::scoped_lock<mutex_type> lk(iFlagList.mutex());
208  if (!is_creating())
209  throw not_creating();
210  iState = lifetime_state::Alive;
211  for (auto i = flags().begin(); i != flags().end();)
212  (*i++)->set_alive();
213  }
214 
215  template <typename FlagList>
217  {
218  std::scoped_lock<mutex_type> lk(iFlagList.mutex());
219  if (!is_destroying())
220  {
221  if (is_destroyed())
222  throw already_destroyed();
224  for (auto i = flags().begin(); i != flags().end();)
225  (*i++)->set_destroying();
226  }
227  }
228 
229  template <typename FlagList>
231  {
232  std::scoped_lock<mutex_type> lk(iFlagList.mutex());
233  if (!is_destroyed())
234  {
235  if (iState == lifetime_state::Creating || iState == lifetime_state::Alive)
236  set_destroying();
237  iState = lifetime_state::Destroyed;
238  for (auto i = flags().begin(); i != flags().end();)
239  (*i++)->set_destroyed();
240  }
241  }
242 
243  template <typename FlagList>
245  {
246  std::scoped_lock<mutex_type> lk(flags().mutex());
247  cookie_type result = flags().insert(&aFlag);
248  switch (iState)
249  {
252  break;
254  aFlag.set_destroying();
255  break;
257  default:
258  aFlag.set_destroying();
259  aFlag.set_destroyed();
260  break;
261  }
262  return result;
263  }
264 
265  template <typename FlagList>
267  {
268  std::scoped_lock<mutex_type> lk(flags().mutex());
269  flags().remove(aFlag.cookie());
270  }
271 
272  template <typename FlagList>
273  inline typename basic_lifetime<FlagList>::flag_list_type& basic_lifetime<FlagList>::flags() const
274  {
275  return iFlagList;
276  }
277 }
cookie_type add_flag(i_lifetime_flag &aFlag) const final
Definition: lifetime.inl:244
bool is_creating() const final
Definition: lifetime.inl:181
virtual void set_destroyed()=0
lifetime_state
Definition: i_lifetime.hpp:66
bool is_destroyed() const final
Definition: lifetime.inl:199
lifetime_state object_state() const final
Definition: lifetime.inl:175
virtual void set_destroying()=0
void set_destroying() override
Definition: lifetime.inl:216
bool is_destroying() const final
Definition: lifetime.inl:193
virtual ~basic_lifetime()
Definition: lifetime.inl:164
bool is_alive() const final
Definition: lifetime.inl:187
uint32_t cookie
Definition: jar.hpp:49
bool is_alive(Object &aObject)
Definition: i_object.hpp:46
void remove_flag(const i_lifetime_flag &aFlag) const final
Definition: lifetime.inl:266
void set_alive() override
Definition: lifetime.inl:205
constexpr bool debug
Definition: json.inl:60
void set_destroyed() override
Definition: lifetime.inl:230
i_lifetime_flag::cookie_type cookie_type
Definition: i_lifetime.hpp:80
lifetime_flag(const i_lifetime &aSubject, owner_pointer aOwner=nullptr)
Definition: lifetime.inl:54
virtual cookie_type cookie() const =0
i_lifetime_flag::cookie_type cookie_type
Definition: i_lifetime.hpp:80