Psi4
ref.h
Go to the documentation of this file.
1 /*
2  * @BEGIN LICENSE
3  *
4  * Psi4: an open-source quantum chemistry software package
5  *
6  * Copyright (c) 2007-2017 The Psi4 Developers.
7  *
8  * The copyrights for code used from other parties are included in
9  * the corresponding files.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License along
22  * with this program; if not, write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  *
25  * @END LICENSE
26  */
27 
28 #ifndef _psi_src_lib_libmints_ref_h_
29 #define _psi_src_lib_libmints_ref_h_
30 
36 #include <cstddef>
37 #include <cstdio>
38 #include <cstdlib>
39 #include <assert.h>
40 
41 // Need to wrap the following into proprocessor wrappers
42 #ifdef HAVE_PTHREAD
43  #include <pthread.h>
44  #define __LOCK(l) pthread_mutex_lock(&l);
45  #define __UNLOCK(l) pthread_mutex_unlock(&l);
46 #else
47  #define __LOCK(l)
48  #define __UNLOCK(l)
49 #endif
50 
51 namespace psi {
52 
53 // For most object counted by Refs we can use the following simple object policy:
55 public:
56  template<typename T> void dispose(T* object) {
57  delete object;
58  }
59 };
60 
61 // Clearly, the above policy will not work for arrays allocated with operator new[].
62 // A replacement policy for this case is trival, fortunately:
64 public:
65  template<typename T> void dispose(T* array) {
66  delete[] array;
67  }
68 };
69 
71 private:
72  size_t* _counter;
73 #ifdef HAVE_PTHREAD
74  pthread_mutex_t _lock;
75 #else
76 #define _lock
77 #endif
78 public:
80  _counter = NULL;
81  }
82 
83 public:
84  template<typename T>
85  void init(T*) {
86  _counter = ::new size_t;
87  *_counter = 1;
88 #ifdef HAVE_PTHREAD
89  // Initialize pthread mutex
90  pthread_mutex_init(&_lock, 0);
91 #endif
92  }
93 
94  template<typename T>
95  void dispose(T*) {
96  __LOCK(_lock);
97  ::delete _counter;
98  _counter = 0;
99  __UNLOCK(_lock);
100 #ifdef HAVE_PTHREAD
101  pthread_mutex_destroy(&_lock);
102 #endif
103  }
104 
105  template<typename T>
106  void increment(T*) {
107  __LOCK(_lock);
108  ++*_counter;
109  __UNLOCK(_lock);
110  }
111 
112  template<typename T> void decrement(T*) {
113  __LOCK(_lock);
114  if (_counter != 0)
115  --*_counter;
116  __UNLOCK(_lock);
117  }
118 
119  template<typename T> bool is_zero(T*) {
120  return _counter?*_counter == 0:true;
121  }
122 };
123 // Reference counting pointer:
124 template<typename T, typename CounterPolicy = SimpleReferenceCount, typename ObjectPolicy = StandardObjectPolicy>
125 class Ref : private CounterPolicy, private ObjectPolicy {
126 protected:
127  // shortcuts
128  typedef CounterPolicy CP;
129  typedef ObjectPolicy OP;
130 
131  T* _object_pointed_to; // Object referred to (or NULL if none)
132  bool _managed; // While false the counter is not incremented/decremented.
133 public:
134  // default constructor
135  Ref() : _managed(true) {
136  _object_pointed_to = NULL;
137  }
138 
139  // Test of copy constructor
140  Ref(T* p) : _managed(true) {
141  _object_pointed_to = NULL;
142  if (p) {
143  init(p);
144  }
145  }
146 
147  // explicit Ref(T* p) {
148  // init(p);
149  // }
150 
151  Ref(Ref<T, CP, OP> const& cp) : CP(static_cast<CP const&>(cp)), OP(static_cast<OP const&>(cp)), _managed(cp._managed) {
152  _object_pointed_to = NULL;
153  attach(cp);
154  }
155 
156  ~Ref() {
157  detach();
158  }
159 
161  assert(p != _object_pointed_to);
162  detach();
163  init(p);
164  return *this;
165  }
166 
169  detach();
170  CP::operator=(static_cast<CP const&>(cp));
171  OP::operator=(static_cast<OP const&>(cp));
172  attach(cp);
173  }
174  return *this;
175  }
176 
177  T* operator-> () const {
178  return _object_pointed_to;
179  }
180 
181  T& operator* () const {
182  return *_object_pointed_to;
183  }
184 
185  void set_managed(bool managed) { _managed = managed; }
186  bool get_managed() const { return _managed; }
187 
188  operator T*() const { return _object_pointed_to; }
189 
190  T* pointer() const {
191  #ifdef DEBUG
192  assert(_object_pointed_to != NULL);
193  #endif
194  return _object_pointed_to;
195  }
196 
197  T& operator[] (int i) const {
198  return _object_pointed_to[i];
199  }
200 private:
201  void init(T* p) {
202  if (p != NULL) {
203  CounterPolicy::init(p);
204  }
205  _object_pointed_to = p;
206  }
207 
208  void attach(Ref<T,CP,OP> const& cp) {
210  _managed = cp._managed;
211  if (cp._object_pointed_to != NULL && _managed) {
212  CounterPolicy::increment(cp._object_pointed_to);
213  }
214  }
215 
216  void detach() {
217  if (_object_pointed_to != NULL && _managed) {
218  CounterPolicy::decrement(_object_pointed_to);
219  if (CounterPolicy::is_zero(_object_pointed_to)) {
220  CounterPolicy::dispose(_object_pointed_to);
221  ObjectPolicy::dispose(_object_pointed_to);
222  }
223  }
224  }
225 };
226 
227 }
228 
229 #endif /*Ref_H_*/
void init(T *p)
Definition: ref.h:201
ObjectPolicy OP
Definition: ref.h:129
T * pointer() const
Definition: ref.h:190
void increment(T *)
Definition: ref.h:106
T * _object_pointed_to
Definition: ref.h:131
Ref< T, CP, OP > & operator=(T *p)
Definition: ref.h:160
#define _lock
Definition: ref.h:76
bool get_managed() const
Definition: ref.h:186
void dispose(T *)
Definition: ref.h:95
Definition: pointgrp.h:105
CounterPolicy CP
Definition: ref.h:128
#define __LOCK(l)
Definition: ref.h:47
Ref(T *p)
Definition: ref.h:140
~Ref()
Definition: ref.h:156
void attach(Ref< T, CP, OP > const &cp)
Definition: ref.h:208
void detach()
Definition: ref.h:216
SimpleReferenceCount()
Definition: ref.h:79
bool is_zero(T *)
Definition: ref.h:119
void set_managed(bool managed)
Definition: ref.h:185
T & operator*() const
Definition: ref.h:181
void init(T *)
Definition: ref.h:85
Definition: ref.h:125
Definition: ref.h:54
void decrement(T *)
Definition: ref.h:112
Definition: ref.h:63
Ref()
Definition: ref.h:135
T * operator->() const
Definition: ref.h:177
Definition: ref.h:70
bool _managed
Definition: ref.h:132
size_t * _counter
Definition: ref.h:72
Ref(Ref< T, CP, OP > const &cp)
Definition: ref.h:151
#define __UNLOCK(l)
Definition: ref.h:48
Definition: PsiFileImpl.h:39
T & operator[](int i) const
Definition: ref.h:197
void dispose(T *array)
Definition: ref.h:65
void dispose(T *object)
Definition: ref.h:56