00001 /* Ergo, version 3.2, a program for linear scaling electronic structure 00002 * calculations. 00003 * Copyright (C) 2012 Elias Rudberg, Emanuel H. Rubensson, and Pawel Salek. 00004 * 00005 * This program is free software: you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation, either version 3 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 * 00018 * Primary academic reference: 00019 * KohnâSham Density Functional Theory Electronic Structure Calculations 00020 * with Linearly Scaling Computational Time and Memory Usage, 00021 * Elias Rudberg, Emanuel H. Rubensson, and Pawel Salek, 00022 * J. Chem. Theory Comput. 7, 340 (2011), 00023 * <http://dx.doi.org/10.1021/ct100611z> 00024 * 00025 * For further information about Ergo, see <http://www.ergoscf.org>. 00026 */ 00027 00036 #ifndef MAT_VALIDPTR 00037 #define MAT_VALIDPTR 00038 namespace mat { 00039 00040 00047 template <typename Tobj> 00048 class ValidPtr { 00049 public: 00051 explicit ValidPtr(Tobj * p) 00052 : ptr(p), inMemory(true), haveDataStructure(false){} 00053 ~ValidPtr() { 00054 delete ptr; 00055 } 00056 00057 /* Pointer can not be changed only object pointed to. 00058 * Therefore this is a const operation. 00059 * Note that if Tobj is const it can not be changed of course. 00060 */ 00061 Tobj & operator*() const { 00062 if (!inMemory) 00063 throw Failure("ValidPtr::operator*() const: " 00064 "Attempt to access invalid object. " 00065 "Object is on file."); 00066 if (!haveDataStructure) 00067 throw Failure("ValidPtr::operator*() const: " 00068 "Attempt to access invalid object. " 00069 "Do not have data structure."); 00070 return *ptr; 00071 } 00072 00073 Tobj * operator->() const { 00074 if (!inMemory) 00075 throw Failure("ValidPtr::operator->() const: " 00076 "Attempt to access invalid pointer." 00077 "Object is on file."); 00078 if (!haveDataStructure) 00079 throw Failure("ValidPtr::operator->() const: " 00080 "Attempt to access invalid pointer. " 00081 "Do not have data structure."); 00082 return ptr; 00083 } 00084 00087 const Tobj & getConstRefForCopying() const { 00088 return *ptr; 00089 } 00090 00091 inline void inMemorySet(bool val) { 00092 inMemory = val; 00093 } 00094 inline bool inMemoryGet() const { 00095 return inMemory; 00096 } 00097 inline void haveDataStructureSet(bool val) { 00098 haveDataStructure = val; 00099 } 00100 inline bool haveDataStructureGet() const { 00101 return haveDataStructure; 00102 } 00103 00104 static void swap( ValidPtr<Tobj> & ptrA, ValidPtr<Tobj> & ptrB ) { 00105 // For the moment, we do not allow swapping ptrs with objs 00106 // written to file. This could be a feature to add but would 00107 // require swapping filenames. 00108 if ( !ptrA.inMemoryGet() || !ptrB.inMemoryGet() ) 00109 throw "Swap called for objects not in memory"; 00110 if ( !ptrA.haveDataStructureGet() || !ptrB.haveDataStructureGet() ) 00111 throw "Swap called for objects without data structure"; 00112 Tobj * tmpPtr = ptrA.ptr; 00113 ptrA.ptr = ptrB.ptr; 00114 ptrB.ptr = tmpPtr; 00115 } 00116 protected: 00117 Tobj * ptr; 00119 bool inMemory; 00121 bool haveDataStructure; 00122 private: 00123 ValidPtr<Tobj>(ValidPtr<Tobj> const &) {} 00124 ValidPtr<Tobj>& operator=(ValidPtr<Tobj> const &) {} 00125 }; 00126 00127 } /* end namespace mat */ 00128 #endif