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