Spinning Topp Logo BlackTopp Studios
inc
managedptr.h
Go to the documentation of this file.
1 // © Copyright 2010 - 2016 BlackTopp Studios Inc.
2 /* This file is part of The Mezzanine Engine.
3 
4  The Mezzanine Engine is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  The Mezzanine Engine is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with The Mezzanine Engine. If not, see <http://www.gnu.org/licenses/>.
16 */
17 /* The original authors have included a copy of the license specified above in the
18  'Docs' folder. See 'gpl.txt'
19 */
20 /* We welcome the use of the Mezzanine engine to anyone, including companies who wish to
21  Build professional software and charge for their product.
22 
23  However there are some practical restrictions, so if your project involves
24  any of the following you should contact us and we will try to work something
25  out:
26  - DRM or Copy Protection of any kind(except Copyrights)
27  - Software Patents You Do Not Wish to Freely License
28  - Any Kind of Linking to Non-GPL licensed Works
29  - Are Currently In Violation of Another Copyright Holder's GPL License
30  - If You want to change our code and not add a few hundred MB of stuff to
31  your distribution
32 
33  These and other limitations could cause serious legal problems if you ignore
34  them, so it is best to simply contact us or the Free Software Foundation, if
35  you have any questions.
36 
37  Joseph Toppi - toppij@gmail.com
38  John Blackwood - makoenergy02@gmail.com
39 */
40 #ifndef _managedptr_h
41 #define _managedptr_h
42 
43 /// @file
44 /// @brief The interface for a class useful for applying RAII when it should have been used but wasn't.
45 
46 #include "datatypes.h"
47 
48 #include "exception.h"
49 
50 namespace Mezzanine
51 {
52  /// @brief Sample implementation for a ManagedPtr
53  /// @details This one is pretty useless, and serves as just an example. Any
54  /// class that implements at least the member function this implements can be used
55  /// with the ManagedPtr to get smart pointer semantics.
56  class IntHandle // This class should serve as an example and should not be exported.
57  {
58  public:
59  /// @brief This is type ManagedPtr will use to work with a handle
60  typedef int* TargetPtrType;
61 
62  /// @brief The Type this handle is pointer at.
63  typedef int TargetType;
64 
65  /// @brief The ManagedPtr never access objects directly, so this is just an implementation detail
66  TargetPtrType Pointer;
67 
68  /// @brief This is expected to leave Pointer in some valid state for dereferencing.
69  void Construct()
70  { Pointer = new int; }
71  /// @brief This can perform any cleanup, but should not fail if Pointer is NULL
72  /// @details Copying or assigning a ManagedPtr just changes which instance of the
73  /// ManagedPtr will cleanup Ptr. This movement of ownership allows passing or
74  /// returning ManagedPtr by value or putting it in a standard container. Only the
75  /// most recent copy will delete the target and none of the earlier copies will.
76  /// This also stops the target from being deleted multiple times.
77  void Deconstruct()
78  { delete Pointer; } //deleting NULL is a no-op, otherwise a check would be needed.
79 
80  /// @brief This is what ManagedPtr will use in copy and assignment operations as well as invaliding handles.
81  /// @param Value The new value for the pointer. If NULL the only thing that the ManagedPtr will do to the handle is call its deconstruct method.
82  void SetPointer(TargetPtrType Value)
83  { Pointer = Value; }
84  /// @brief This is what the ManagedPtr with use for dereferencing.
85  /// @return The pointer to the managed data. This is expected to return a value that resolves to false when used as a condition when invalid.
86  TargetPtrType GetPointer()
87  { return Pointer; }
88 
89  };
90 
91 
92  /// @brief This is used to get RAII semantics when not provided inherently.
93  /// @details Some APIs have functions that return raw pointers and expect the call to clean
94  /// up the mess. Even worse sometimes doing this involves more than
95  /// This is exactly the size of the handle class used. It could be as small as raw pointer
96  /// if constructed carefully.
97  /// @n @n
98  /// To use this a 'Handle' must be created first. A good handle is trivial copyable, assignable
99  /// and implements a few functions. This is similar to the Pimpl idiom in that the details of the
100  /// implemention could be abstracted into this 'Handle'. The 'Handle' will encapsulate/have the
101  /// knowledge of how to correctly create and destroy the pointer while the ManagedPtr provides
102  /// The pointer-like semantics and esures it is destructed exactly once.
103  /// This is expected to have members:
104  /// - TargetPtrType - The type of the underlying pointer.
105  /// - void Construct() - Called on initial construction.
106  /// - void SetPointer(TargetPtrType Value) - called for copy construction, assignements and with NULL Value for invalidations.
107  /// - TargetPtrType GetPointer() - for dereferencing.
108  /// - void Deconstruct() - For cleanup/deconstruction.
109  ///
110  /// The semantics of this class also presume that copying and assigning a Handle is safe. To do that
111  /// uses these functions as well. It is intended that pointer copies be shallow copies.
112  /// - operator= - For copying one handle to another, used in construction.
113  /// - Sane default construction that can immediately allow for calls to the the other functions.
114  template <class Handle>
116  {
117  private:
118  /// @brief This handles the details of contructing and managing the raw pointer.
119  Handle Target;
120 
121  /// @brief Copy the state of one handle to this handle, and invalidate the old one
122  /// @param StatefulHandle the state to copy onto our handle.
123  void Copy(Handle& StatefulHandle)
124  {
125  if(StatefulHandle.GetPointer()!=Target.GetPointer())
126  {
127  Target.Deconstruct();
128  Target=StatefulHandle;
129  Invalidate(StatefulHandle);
130  }
131  }
132 
133  /// @brief Take whatever actions are required to invalidate a handle.
134  /// @param StatefulHandle The Handle to invalidate.
135  static void Invalidate(Handle& StatefulHandle)
136  { StatefulHandle.SetPointer(NULL); }
137  /// @brief Invalidate the handle on this ManagedPtr.
138  void Invalidate()
139  { Invalidate(Target); }
140 
141  public:
142 
143  /// @brief Used to set the return type of pointer like returns (could be a smartpointer)
144  typedef typename Handle::TargetPtrType TargetPtrType;
145  /// @brief Used to set the value and reference type for returns.
146  typedef typename Handle::TargetType TargetType;
147 
148  /// @brief Constructs the target after passing it the desired state information
149  /// @param StatefulHandle A way to pass parameters into the constructors of the underlying class being targeted.
150  /// @details The Handle class can be implemented any way that is appropriate for the underlying data. So it is
151  /// not limited to the members defined here. This constructor will call the copy copystructor of the handle before
152  /// Calling Construct() on it.
153  ManagedPtr(Handle StatefulHandle = Handle())
154  : Target( StatefulHandle )
155  {
156  Target.Construct();
157  }
158 
159  /// @brief Creates the Target from an already constructed one but invalidates Other ManagedPtr
160  /// @details This transfer ownership (who will deconstruct the handle) from the Other ManagedPtr to this one. This
161  /// Does not call Construct().
162  /// @param Other The ManagedPtr to copy then invalidate.
164  {
165  Target=Other.Target;
166  Other.Target.SetPointer(NULL);
167  }
168 
169  /// @brief Assigns the Target but invalidates Other ManagedPtr
170  /// @details This transfer ownership (who will deconstruct the handle) from the Other
171  /// ManagedPtr to this one. This Does not call Construct().
172  /// @param Other The ManagedPtr to copy then invalidate.
173  /// @return A reference to this ManagedPtr to allow operator chaining.
174  ManagedPtr& operator= (ManagedPtr& Other)
175  {
176  Copy(Other.Target);
177  return *this;
178  }
179 
180  /// @brief Dereference operator.
181  /// @return The managed object is returned by reference.
182  /// @throw If the pointerNothing This member function does not throw exceptions unless the underlying handle does.
183  TargetType& operator*()
184  {
185  TargetPtrType Results=Target.GetPointer();
186  if(Results)
187  { return *Results; }
188  else
189  { MEZZ_EXCEPTION(ExceptionBase::MM_EXCEPTION,"Attempted to Dereference a NULL ManagedPtr."); }
190  }
191 
192  /// @brief The Structure dereference operator.
193  /// @return Makes it appear, syntactically, as though you are dereferencing the raw pointer.
194  TargetPtrType operator->()
195  {
196  TargetPtrType Results=Target.GetPointer();
197  if(Results)
198  { return Results; }
199  else
200  { MEZZ_EXCEPTION(ExceptionBase::MM_EXCEPTION,"Attempted to Dereference a NULL ManagedPtr."); }
201  }
202 
203  /// @brief Get the raw pointer to the managed object.
204  /// @return The raw pointer to the managed object or 0 if this pointer is invalid.
205  /// @note This name was chosen to match standard compliant names, and should be usable in templates that require this function.
206  TargetPtrType Get()
207  { return Target.GetPointer(); }
208 
209  /// @copydoc Get
210  /// @note Provided to match method names on standard smart pointers
211  TargetPtrType get()
212  { return Get(); }
213 
214  /// @brief Returns true if this pointer points to something.
215  /// @warning Without C++11 this can be accidentally easily be cast to a bool and can do silly things, like bogus pointer multiplication.
216  operator Boole()
217  { return 0 != Target.GetPointer(); }
218 
219  /// @brief Compares the underlying pointer of this and another ManagedPtr, (This had better return false)
220  /// @param Other The right hand portion of the comparison
221  /// @return Bool Hopefully thi is false, becase
222  Boole operator== (ManagedPtr& Other)
223  { return Target.GetPointer() == Other.Target.GetPointer(); }
224 
225  /// @brief Destroy the target and invalidate it.
227  {
228  Target.Deconstruct();
229  Target.SetPointer(NULL);
230  }
231  };
232 
233 
234 } // /namespace Mezzanine
235 
236 #endif // Include guard
void SetPointer(TargetPtrType Value)
This is what ManagedPtr will use in copy and assignment operations as well as invaliding handles...
Definition: managedptr.h:82
Handle::TargetType TargetType
Used to set the value and reference type for returns.
Definition: managedptr.h:146
TargetPtrType Pointer
The ManagedPtr never access objects directly, so this is just an implementation detail.
Definition: managedptr.h:66
bool Boole
Generally acts a single bit, true or false.
Definition: datatypes.h:173
void Construct()
This is expected to leave Pointer in some valid state for dereferencing.
Definition: managedptr.h:69
#define MEZZ_EXCEPTION(num, desc)
An easy way to throw exceptions with rich information.
Definition: exception.h:3048
All the definitions for datatypes as well as some basic conversion functions are defined here...
int * TargetPtrType
This is type ManagedPtr will use to work with a handle.
Definition: managedptr.h:60
int TargetType
The Type this handle is pointer at.
Definition: managedptr.h:63
TargetType & operator*()
Dereference operator.
Definition: managedptr.h:183
Handle::TargetPtrType TargetPtrType
Used to set the return type of pointer like returns (could be a smartpointer)
Definition: managedptr.h:144
This implements the exception hiearchy for Mezzanine.
This is used to get RAII semantics when not provided inherently.
Definition: managedptr.h:115
void Deconstruct()
This can perform any cleanup, but should not fail if Pointer is NULL.
Definition: managedptr.h:77
TargetPtrType GetPointer()
This is what the ManagedPtr with use for dereferencing.
Definition: managedptr.h:86
TargetPtrType operator->()
The Structure dereference operator.
Definition: managedptr.h:194
Sample implementation for a ManagedPtr.
Definition: managedptr.h:56
#define MEZZ_LIB
Some platforms require special decorations to denote what is exported/imported in a share library...
The bulk of the engine components go in this namspace.
Definition: actor.cpp:56
ManagedPtr(Handle StatefulHandle=Handle())
Constructs the target after passing it the desired state information.
Definition: managedptr.h:153
~ManagedPtr()
Destroy the target and invalidate it.
Definition: managedptr.h:226
TargetPtrType Get()
Get the raw pointer to the managed object.
Definition: managedptr.h:206
ManagedPtr(ManagedPtr &Other)
Creates the Target from an already constructed one but invalidates Other ManagedPtr.
Definition: managedptr.h:163
Thrown when an unknown memory management exception occurs.
Definition: exception.h:96