The Battle for Wesnoth  1.19.15+dev
lua_ptr.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2020 - 2025
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include <memory>
18 template<typename T>
19 class lua_ptr;
20 
21 /**
22  * Allows creation of lua_ptr<T> instances, but does not affect the lifetime of the T itself.
23  * This allows the instance of T to be deleted while the lua_ptr<T>s still exist.
24  *
25  * The implementation details are making a shared_ptr<non-owning raw pointer to T>, with that
26  * shared_ptr owned by the instance of T that's being pointed to, which is then used to create
27  * weak_ptrs. The lua_ptr is a wrapper to make sure that no-one gets a second non-temporary
28  * shared_ptr<non-owning raw pointer T>. As there's only one shared_ptr, the weak_ptrs become
29  * invalid (but defined behavior) when the instance of T is deleted, because that deletes the
30  * shared_ptr.
31  */
32 template<typename T>
34 {
35 public:
36  enable_lua_ptr(T* tp) : self_(std::make_shared<T*>(tp)) {}
37 
38  /**
39  * The weak_ptrs are pointing to o's shared_ptr's control block, so to keep existing
40  * weak_ptrs valid the existing control block is reused instead of replaced.
41  *
42  * After the move, the existing control block will point to the new T, and o.self_ will be
43  * empty (which is guaranteed by the specification for std::shared_ptr's move assignment
44  * operator).
45  */
47  {
48  *self_ = static_cast<T*>(this);
49  }
51  {
52  self_ = std::move(o.self_);
53  *self_ = static_cast<T*>(this);
54  return *this;
55  }
56 private:
57  enable_lua_ptr(const enable_lua_ptr& o) = delete;
59  friend class lua_ptr<T>;
60  std::shared_ptr<T*> self_;
61 };
62 
63 /** T must inherit enable_lua_ptr<T> */
64 template<typename T>
65 class lua_ptr
66 {
67 public:
69  T* get_ptr()
70  {
71  if(auto pp = self_.lock()) {
72  return *pp;
73  }
74  return nullptr;
75  }
77  {
78  return get_ptr();
79  }
80  operator bool() const
81  {
82  return bool(self_.lock());
83  }
84  bool operator!() const
85  {
86  return !operator bool();
87  }
88  std::weak_ptr<T*> self_;
89 };
Allows creation of lua_ptr<T> instances, but does not affect the lifetime of the T itself.
Definition: lua_ptr.hpp:34
enable_lua_ptr(enable_lua_ptr &&o)
The weak_ptrs are pointing to o's shared_ptr's control block, so to keep existing weak_ptrs valid the...
Definition: lua_ptr.hpp:46
enable_lua_ptr(const enable_lua_ptr &o)=delete
std::shared_ptr< T * > self_
Definition: lua_ptr.hpp:60
enable_lua_ptr & operator=(enable_lua_ptr &&o)
Definition: lua_ptr.hpp:50
enable_lua_ptr(T *tp)
Definition: lua_ptr.hpp:36
T must inherit enable_lua_ptr<T>
Definition: lua_ptr.hpp:66
bool operator!() const
Definition: lua_ptr.hpp:84
T * operator->()
Definition: lua_ptr.hpp:76
lua_ptr(enable_lua_ptr< T > &o)
Definition: lua_ptr.hpp:68
std::weak_ptr< T * > self_
Definition: lua_ptr.hpp:88
T * get_ptr()
Definition: lua_ptr.hpp:69