Odamex
Setting the Standard in Multiplayer Doom
common/szp.h
Go to the documentation of this file.
00001 // Emacs style mode select   -*- C++ -*- 
00002 //-----------------------------------------------------------------------------
00003 //
00004 // $Id: szp.h 1788 2010-08-24 04:42:57Z russellrice $
00005 //
00006 // Copyright (C) 2006-2010 by The Odamex Team.
00007 //
00008 // This program is free software; you can redistribute it and/or
00009 // modify it under the terms of the GNU General Public License
00010 // as published by the Free Software Foundation; either version 2
00011 // of the License, or (at your option) any later version.
00012 //
00013 // This program is distributed in the hope that it will be useful,
00014 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00015 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016 // GNU General Public License for more details.
00017 //
00018 // DESCRIPTION:
00019 //
00020 //  denis - szp<T>, the self zeroing pointer
00021 //  
00022 //  Once upon a time, actors held raw pointers to other actors. 
00023 //  
00024 //  To destroy an object, one cycled though all the others searching for its 
00025 //  pointer and resetting every copy to NULL. Then one did the cycling for 
00026 //  the players, then the sector sound origins, and so on; with hack upon 
00027 //  hack. Ironically, zero dereferencing is what often crashed the 
00028 //  program altogether.
00029 //  
00030 //  The idea behind szp is that all copies of one szp pointer can be made 
00031 //  to point to the same object in O(1) time. This means that having a 
00032 //  single szp of an actor, you can set them all to NULL without iteration. 
00033 //  And, as a bonus, on every pointer access, a NULL check can throw a 
00034 //  specific exception. Naturally, you should always be careful with pointers.
00035 //
00036 //-----------------------------------------------------------------------------
00037 
00038 
00039 #ifndef __SZP_H__
00040 #define __SZP_H__
00041 
00042 #include "errors.h"
00043 
00044 
00045 template <typename T>
00046 class szp
00047 {
00048         // pointer to a common raw pointer
00049         T **naive;
00050 
00051         // circular linked list
00052         szp *prev, *next;
00053 
00054         // this should never be used
00055         // spawn from other pointers, or use init()
00056         szp &operator =(T *other) {};
00057 
00058         // utility function to remove oneself from the linked list
00059         void inline unlink()
00060         {
00061                 if(!next)
00062                         return;
00063 
00064                 next->prev = prev;
00065                 prev->next = next;
00066                         
00067                 if(!naive)
00068                         return;
00069 
00070                 // last in ring?
00071                 if(this == next)
00072                         delete naive;
00073                         
00074                 naive = NULL;
00075         }
00076         
00077 public:
00078 
00079         // use as pointer, checking validity
00080         inline T* operator ->()
00081         {
00082                 if(!naive || !*naive)
00083                         throw CRecoverableError("szp pointer was NULL");
00084 
00085                 return *naive;
00086         }
00087         
00088         // use as raw pointer
00089         inline operator T*()
00090         {
00091                 if(!naive)
00092                         return NULL;
00093                 else
00094                         return *naive;
00095         }
00096 
00097         // this function can update or zero all related pointers
00098         void update_all(T *target)
00099         {
00100                 if(!naive)
00101                         throw CRecoverableError("szp pointer was NULL on update_all");
00102                 
00103                 // all copies already have naive, so their pointers will update too
00104                 *naive = target;
00105         }
00106         
00107         // copy a pointer and add self to the "i have this pointer" list
00108         inline szp &operator =(szp other)
00109         {
00110                 // itself?
00111                 if(&other == this)
00112                         return *this;
00113 
00114                 unlink();
00115 
00116                 if(!other.prev || !other.next || !other.naive)
00117                 {
00118                         next = prev = this;
00119                         return *this;
00120                 }
00121                 
00122                 // link
00123                 naive = other.naive;
00124                 prev = other.next->prev;
00125                 next = other.next;
00126                 prev->next = next->prev = this;
00127                 
00128                 return *this;
00129         }
00130         
00131         // creates the first (original) pointer
00132         void init(T *target)
00133         {
00134                 unlink();
00135                 
00136                 // first link
00137                 naive = new T*(target);
00138                 prev = next = this;
00139         }
00140         
00141         // cheap constructor
00142         inline szp()
00143                 : naive(NULL), prev(NULL), next(NULL)
00144         { }
00145         
00146         // copy constructor
00147         inline szp(const szp &other)
00148                 : naive(NULL)
00149         {
00150                 if(!other.prev || !other.next || !other.naive)
00151                 {
00152                         prev = next = this;
00153                         return;
00154                 }
00155                 
00156                 // link
00157                 naive = other.naive;
00158                 prev = other.next->prev;
00159                 next = other.next;
00160                 prev->next = next->prev = this;
00161         }
00162 
00163         // unlink from circular list on destruction
00164         inline ~szp()
00165         {
00166                 unlink();
00167         }
00168 };
00169 
00170 #endif // __SZP_H__
00171 
00172 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends