The Battle for Wesnoth  1.19.5+dev
fake_unit_ptr.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2014 - 2024
3  by Chris Beck <render787@gmail.com>
4  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY.
12 
13  See the COPYING file for more details.
14 */
15 
16 #include "fake_unit_ptr.hpp"
17 
18 #include "fake_unit_manager.hpp"
19 #include "resources.hpp"
20 #include "units/unit.hpp"
21 
22 fake_unit_ptr::fake_unit_ptr() : unit_(), my_manager_(nullptr) {}
23 fake_unit_ptr::fake_unit_ptr(const internal_ptr & u) : unit_(u), my_manager_(nullptr) {}
24 fake_unit_ptr::fake_unit_ptr(const internal_ptr & u, fake_unit_manager * mgr) : unit_(u), my_manager_(nullptr)
25 {
27 }
29  : unit_(ptr.unit_)
30  , my_manager_(nullptr)
31 {}
32 
34  : unit_(std::move(ptr.unit_))
35  , my_manager_(ptr.my_manager_)
36 {
37  ptr.my_manager_ = nullptr;
38 }
39 
41  std::swap(unit_, o.unit_);
43 }
44 
46  swap(other);
47  return *this;
48 }
49 
50 
51 /**
52  * Assignment operator, taking a unit.
53  * If already in the queue, @a this will be moved to the end of the
54  * queue (drawn last).
55  *
56  * This function is unsuitable for derived classes and MUST be overridden.
57  * Furthermore, derived classes must not explicitly call this version.
58  *
59  * The overriding function can be almost the same, except "new (this)" should
60  * be followed by the derived class instead of "fake_unit(a)".
61  */
62 /*fake_unit & fake_unit::operator=(const unit& a)
63 {
64  if ( this != &a ) {
65  fake_unit_manager * mgr = my_manager_;
66 
67  // Use the copy constructor to make sure we are coherent.
68  // (Methodology copied from unit::operator=)
69  this->~fake_unit();
70  new (this) fake_unit(a);
71  // Restore our old manager.
72  if ( mgr != nullptr )
73  place_on_fake_unit_manager(mgr);
74  }
75  return *this;
76 }*/
77 
78 /**
79  * Removes the unit from the fake manager, and resets the internal unit pointer.
80  * After this, both pointers are null.
81  */
83 {
85  unit_.reset();
86 }
87 
88 /**
89  * Resets the internal unit pointer to match the given pointer.
90  * The value of my_manager_ is preserved -- the old unit is deregistered,
91  * and the new unit is registered with the same manager.
92  */
94 {
95  if (unit_.get() != ptr.get()) {
97 
99  unit_ = ptr;
100  if (mgr)
102  }
103 }
104 
105 /**
106  * Removes @a this from the fake_units_ list if necessary.
107  */
109 {
110  try {
111  // The fake_unit class exists for this one line, which removes the
112  // fake_unit from the managers's fake_units_ dequeue in the event of an
113  // exception.
114  if(my_manager_) {
115  //my_manager_ points to resources::fake_units, the next line fixes a bug whre this code would attempt to access a freed fake_unit_manager object, see https://github.com/wesnoth/wesnoth/issues/3008
116  if(resources::fake_units != nullptr) {
118  }
119  }
120 
121  } catch (...) {}
122 }
123 
124 /**
125  * Place @a this on @a manager's fake_units_ dequeue.
126  * This will be added at the end (drawn last, over all other units).
127  * Duplicate additions are not allowed.
128  */
130  assert(my_manager_ == nullptr); //Can only be placed on 1 fake_unit_manager
131  my_manager_=manager;
133 }
134 
135 /**
136  * Removes @a this from whatever fake_units_ list it is on (if any).
137  * @returns the number of fake_units deleted, which should be 0 or 1
138  * (any other number indicates an error).
139  */
141  int ret(0);
142  if(my_manager_ != nullptr){
144  my_manager_=nullptr;
145  }
146  return ret;
147 }
Manages a list of fake units for the display object.
void place_temporary_unit(internal_ptr_type)
Register a unit with this manager.
int remove_temporary_unit(internal_ptr_type)
Deregister a unit from this manager.
Holds a temporary unit that can be drawn on the map without being placed in the unit_map.
void reset()
Reset the internal unit pointer, and deregister from the manager.
fake_unit_manager * my_manager_
Raw pointer to the manager.
unit_ptr internal_ptr
~fake_unit_ptr()
Removes this from the fake_units_ list if necessary.
fake_unit_ptr & operator=(fake_unit_ptr other)
Copy assignment operator using copy-and-swap idiom.
void swap(fake_unit_ptr &o)
Pointer swap.
int remove_from_fake_unit_manager()
Removes this from whatever fake_units_ list it is on (if any).
internal_ptr unit_
Internal unit pointer.
void place_on_fake_unit_manager(fake_unit_manager *d)
Place this on manager's fake_units_ dequeue.
void swap(config &lhs, config &rhs)
Implement non-member swap function for std::swap (calls config::swap).
Definition: config.cpp:1343
const unit * unit_
fake_unit_manager * fake_units
Definition: resources.cpp:30