1 /* Ergo, version 3.8, a program for linear scaling electronic structure
2  * calculations.
3  * Copyright (C) 2019 Elias Rudberg, Emanuel H. Rubensson, Pawel Salek,
4  * and Anastasia Kruchinina.
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 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Primary academic reference:
20  * Ergo: An open-source program for linear-scaling electronic structure
21  * calculations,
22  * Elias Rudberg, Emanuel H. Rubensson, Pawel Salek, and Anastasia
23  * Kruchinina,
24  * SoftwareX 7, 107 (2018),
25  * <http://dx.doi.org/10.1016/j.softx.2018.03.005>
26  *
27  * For further information about Ergo, see <http://www.ergoscf.org>.
28  */
29 
30 /** @file ValidPtr.h Smart pointer class to control access to object.
31  *
32  * Copyright(c) Emanuel Rubensson 2006
33  *
34  * @author Emanuel Rubensson  @a responsible @a author
35  * @date November 2006
36  *
37  */
38 #ifndef MAT_VALIDPTR
39 #define MAT_VALIDPTR
40 namespace mat {
41 
42 
43   /** Smart pointer class to control access to object
44    *
45    * Primary use:
46    * Control access to objects that may be written to file.
47    *
48    */
49   template <typename Tobj>
50     class ValidPtr {
51   public:
52     /** Copy ordinary pointer constructor */
ValidPtr(Tobj * p)53     explicit ValidPtr(Tobj * p)
54       : ptr(p), inMemory(true), haveDataStructure(false){}
~ValidPtr()55     ~ValidPtr() {
56       delete ptr;
57     }
58 
59       /* Pointer can not be changed only object pointed to.
60        * Therefore this is a const operation.
61        * Note that if Tobj is const it can not be changed of course.
62        */
63       Tobj & operator*() const {
64 	if (!inMemory)
65 	  throw Failure("ValidPtr::operator*() const: "
66 			"Attempt to access invalid object. "
67 			"Object is on file.");
68 	if (!haveDataStructure)
69 	  throw Failure("ValidPtr::operator*() const: "
70 			"Attempt to access invalid object. "
71 			"Do not have data structure.");
72 	return *ptr;
73       }
74 
75       Tobj * operator->() const {
76 	if (!inMemory)
77 	  throw Failure("ValidPtr::operator->() const: "
78 			"Attempt to access invalid pointer."
79 			"Object is on file.");
80 	if (!haveDataStructure)
81 	  throw Failure("ValidPtr::operator->() const: "
82 			"Attempt to access invalid pointer. "
83 			"Do not have data structure.");
84 	return ptr;
85       }
86 
87       /** getConstRefForCopying() is provided to make it possible to
88 	  copy the object also when it is written to file. */
getConstRefForCopying()89       const Tobj & getConstRefForCopying() const {
90 	return *ptr;
91       }
92 
inMemorySet(bool val)93       inline void inMemorySet(bool val) {
94 	inMemory = val;
95       }
inMemoryGet()96       inline bool inMemoryGet() const {
97 	return inMemory;
98       }
haveDataStructureSet(bool val)99       inline void haveDataStructureSet(bool val) {
100 	haveDataStructure = val;
101       }
haveDataStructureGet()102       inline bool haveDataStructureGet() const {
103 	return haveDataStructure;
104       }
105 
swap(ValidPtr<Tobj> & ptrA,ValidPtr<Tobj> & ptrB)106       static void swap( ValidPtr<Tobj> & ptrA, ValidPtr<Tobj> & ptrB ) {
107 	// For the moment, we do not allow swapping ptrs with objs
108 	// written to file. This could be a feature to add but would
109 	// require swapping filenames.
110 	if ( !ptrA.inMemoryGet() ||  !ptrB.inMemoryGet() )
111 	  throw "Swap called for objects not in memory";
112 	if ( !ptrA.haveDataStructureGet() ||  !ptrB.haveDataStructureGet() )
113 	  throw "Swap called for objects without data structure";
114 	Tobj * tmpPtr = ptrA.ptr;
115 	ptrA.ptr = ptrB.ptr;
116 	ptrB.ptr = tmpPtr;
117       }
118   protected:
119       Tobj * ptr;
120       /** Access to ptr forbidden if inMemory is false */
121       bool inMemory;
122       /** Access to ptr forbidden if haveDataStructure is false */
123       bool haveDataStructure;
124   private:
125       ValidPtr<Tobj>(ValidPtr<Tobj> const &) {}
126       ValidPtr<Tobj>& operator=(ValidPtr<Tobj> const &) {}
127   };
128 
129 }  /* end namespace mat */
130 #endif
131