MezzanineEngine 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
managedptr.h
Go to the documentation of this file.
1 // © Copyright 2010 - 2014 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
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.
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.
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  /// - TargetPtrType - The type of the underlying pointer.
106  /// - void Construct() - Called on initial construction.
107  /// - void SetPointer(TargetPtrType Value) - called for copy construction, assignements and with NULL Value for invalidations.
108  /// - TargetPtrType GetPointer() - for dereferencing.
109  /// - void Deconstruct() - For cleanup/deconstruction.
110  ///
111  /// The semantics of this class also presume that copying and assigning a Handle is safe. To do that
112  /// uses these functions as well. It is intended that pointer copies be shallow copies.
113  /// - operator= - For copying one handle to another, used in construction.
114  /// - Sane default construction that can immediately allow for calls to the the other functions.
115  template <class Handle>
117  {
118  private:
119  /// @brief This handles the details of contructing and managing the raw pointer.
120  Handle Target;
121 
122  /// @brief Copy the state of one handle to this handle, and invalidate the old one
123  /// @param StatefulHandle the state to copy onto our handle.
124  void Copy(Handle& StatefulHandle)
125  {
126  if(StatefulHandle.GetPointer()!=Target.GetPointer())
127  {
128  Target.Deconstruct();
129  Target=StatefulHandle;
130  Invalidate(StatefulHandle);
131  }
132  }
133 
134  /// @brief Take whatever actions are required to invalidate a handle.
135  /// @param StatefulHandle The Handle to invalidate.
136  static void Invalidate(Handle& StatefulHandle)
137  { StatefulHandle.SetPointer(NULL); }
138  /// @brief Invalidate the handle on this ManagedPtr.
139  void Invalidate()
140  { Invalidate(Target); }
141 
142  public:
143 
144  /// @brief Used to set the return type of pointer like returns (could be a smartpointer)
145  typedef typename Handle::TargetPtrType TargetPtrType;
146  /// @brief Used to set the value and reference type for returns.
147  typedef typename Handle::TargetType TargetType;
148 
149  /// @brief Constructs the target after passing it the desired state information
150  /// @param StatefulHandle A way to pass parameters into the constructors of the underlying class being targeted.
151  /// @details The Handle class can be implemented any way that is appropriate for the underlying data. So it is
152  /// not limited to the members defined here. This constructor will call the copy copystructor of the handle before
153  /// Calling Construct() on it.
154  ManagedPtr(Handle StatefulHandle = Handle())
155  {
156  Target=StatefulHandle;
157  Target.Construct();
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 ManagedPtr to this one. This
171  /// Does not call Construct().
172  /// @param Other The ManagedPtr to copy then invalidate.
173  ManagedPtr& operator= (ManagedPtr& Other)
174  {
175  Copy(Other.Target);
176  return *this;
177  }
178 
179  /// @brief Dereference operator.
180  /// @return The managed object is returned by reference.
181  /// @throw If the pointerNothing This member function does not throw exceptions unless the underlying handle does.
183  {
184  TargetPtrType Results=Target.GetPointer();
185  if(Results)
186  { return *Results; }
187  else
188  { MEZZ_EXCEPTION(Exception::MM_EXCEPTION,"Attempted to Dereference a NULL ManagedPtr."); }
189  }
190 
191  /// @brief The Structure dereference operator.
192  /// @return Makes it appear, syntactically, as though you are dereferencing the raw pointer.
194  {
195  TargetPtrType Results=Target.GetPointer();
196  if(Results)
197  { return Results; }
198  else
199  { MEZZ_EXCEPTION(Exception::MM_EXCEPTION,"Attempted to Dereference a NULL ManagedPtr."); }
200  }
201 
202  /// @brief Get the raw pointer to the managed object.
203  /// @return The raw pointer to the managed object or 0 if this pointer is invalid.
204  /// @note This name was chosen to match standard compliant names, and should be usable in templates that require this function.
206  { return Target.GePointer(); }
207 
208  /// @copydoc Get
209  /// @note Provided to match method names on standard smart pointers
211  { return Get(); }
212 
213  /// @brief Returns true if this pointer points to something.
214  /// @warning Without C++11 this can be accidentally easily be cast to a bool and can do silly things, like bogus pointer multiplication.
215  operator bool()
216  { return 0 != Target.GetPointer(); }
217 
218  /// @brief Compares the underlying pointer of this and another ManagedPtr, (This had better return false)
219  /// @param Other The right hand portion of the comparison
220  /// @return Bool Hopefully thi is false, becase
221  bool operator== (ManagedPtr& Other)
222  { return Target.GetPointer() == Other.Target.GetP0inter(); }
223 
224  /// @brief Destroy the target and invalidate it.
226  {
227  Target.Deconstruct();
228  Target.SetPointer(NULL);
229  }
230  };
231 
232 
233 } // /namespace Mezzanine
234 
235 #endif // Include guard