source: ThirdParty/mpqc_open/src/lib/util/ref/ref.h@ 398fcd

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 398fcd was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 15.4 KB
Line 
1//
2// ref.h --- definitions of the reference counting classes
3//
4// Copyright (C) 1996 Limit Point Systems, Inc.
5//
6// Author: Curtis Janssen <cljanss@limitpt.com>
7// Maintainer: LPS
8//
9// This file is part of the SC Toolkit.
10//
11// The SC Toolkit is free software; you can redistribute it and/or modify
12// it under the terms of the GNU Library General Public License as published by
13// the Free Software Foundation; either version 2, or (at your option)
14// any later version.
15//
16// The SC Toolkit 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 Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public License
22// along with the SC Toolkit; see the file COPYING.LIB. If not, write to
23// the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
24//
25// The U.S. Government is granted a limited license as per AL 91-7.
26//
27
28// This is the main include file for the reference counting classes.
29// This includes two other files: reftmpl.h and refmacr.h. The
30// former is a template declaration for the reference counted classes
31// and the latter is generated from the former by a perl script and
32// provides CPP macros that declare reference counting classes.
33//
34// The behaviour of the package can be modified with the following five
35// macros, each of which should be undefined, 0, or 1:
36//
37// REF_CHECK_STACK: If this is 1 referenced objects are checked to see if they
38// reside on the stack, in which case storage for the object is not managed,
39// if management is enabled. This feature can be confused by multiple threads
40// and memory checking libraries.
41//
42// REF_MANAGE: If this is 1 the manage and unmanage members are enabled.
43//
44// REF_CHECK_MAX_NREF: If this is 1 the reference count is checked before
45// it is incremented to make sure it isn't too big.
46//
47// REF_CHECK_MIN_NREF: If this is 1 the reference count is checked before
48// it is decremented to make sure it isn't already zero.
49//
50// REF_USE_LOCKS: If this is 1 then critical regions are locked before they
51// are entered. This prevents erroneous behavior when multiple threads
52// share reference counted objects. This will slow down certain operations,
53// so it should be set to 0 if your application does not need to be thread
54// safe.
55//
56// If a macro is undefined, then the behaviour is architecture
57// dependent--usually, the macro will be set to 1 in this case.
58// For maximum efficiency and for normal operation after the program is
59// debugged, compile with all of the above macros defined to zero.
60// This can also be done with -DREF_OPTIMIZE.
61//
62// An include file can be used to set these options as well. This has
63// the advantage that dependency checking will force an automatic
64// recompile of all affected files if the options change. The file
65// <scconfig.h> will be include if -DHAVE_CONFIG_H is specified.
66//
67// Note that all source code that uses references must be compiled with
68// the same value REF_MANAGE. Changing this can change the storage layout
69// and the interpretation of the reference count data.
70
71
72#ifdef __GNUC__
73#pragma interface
74#endif
75
76#ifndef _util_ref_ref_h
77#define _util_ref_ref_h
78
79#include <iostream>
80#include <stdlib.h>
81#include <limits.h>
82
83#include <util/ref/identity.h>
84
85#ifdef HAVE_CONFIG_H
86#include <scconfig.h>
87#endif
88
89#ifdef REF_OPTIMIZE
90#ifndef REF_CHECK_STACK
91# define REF_CHECK_STACK 0
92#endif
93#ifndef REF_MANAGE
94# define REF_MANAGE 0
95#endif
96#ifndef REF_CHECK_MAX_NREF
97# define REF_CHECK_MAX_NREF 0
98#endif
99#ifndef REF_CHECK_MIN_NREF
100# define REF_CHECK_MIN_NREF 0
101#endif
102#endif
103
104#ifdef SUNMOS
105#ifndef REF_CHECK_STACK
106#define REF_CHECK_STACK 0
107#endif
108#else
109#ifndef REF_CHECK_STACK
110#define REF_CHECK_STACK 0
111#endif
112#endif
113
114#ifndef REF_MANAGE
115#define REF_MANAGE 1
116#endif
117
118#ifndef REF_CHECK_MAX_NREF
119#define REF_CHECK_MAX_NREF 1
120#endif
121
122#ifndef REF_CHECK_MIN_NREF
123#define REF_CHECK_MIN_NREF 1
124#endif
125
126#ifndef REF_USE_LOCKS
127# if HAVE_STHREAD || HAVE_CREATETHREAD || HAVE_PTHREAD
128# define REF_USE_LOCKS 1
129# endif
130#endif
131
132#ifndef REF_ALWAYS_USE_LOCKS
133# define REF_ALWAYS_USE_LOCKS 1
134#endif
135
136#if REF_CHECK_STACK
137#include <unistd.h>
138#ifndef HAVE_SBRK_DEC
139extern "C" void * sbrk(ssize_t);
140#endif
141#define DO_REF_CHECK_STACK(p) (((void*) (p) > sbrk(0)) && (p)->managed())
142#else // REF_CHECK_STACK
143#define DO_REF_CHECK_STACK(p) (0)
144#endif // REF_CHECK_STACK
145
146#if REF_MANAGE
147#define DO_REF_UNMANAGE(p) ((p)->unmanage())
148#else // REF_MANAGE
149#define DO_REF_UNMANAGE(p)
150#endif // REF_MANAGE
151
152#if REF_USE_LOCKS
153#define __REF_LOCK__(p) p->lock_ptr()
154#define __REF_UNLOCK__(p) p->unlock_ptr()
155#if REF_ALWAYS_USE_LOCKS
156#define __REF_INITLOCK__() use_locks(true)
157#else
158#define __REF_INITLOCK__() ref_lock_ = 0xff
159#endif
160#else
161#define __REF_LOCK__(p)
162#define __REF_UNLOCK__(p)
163#define __REF_INITLOCK__()
164#endif
165
166namespace sc {
167
168typedef unsigned long refcount_t;
169
170/** The base class for all reference counted objects. If multiple
171 inheritance is used, RefCount must be virtually inherited from,
172 otherwise references to invalid memory will likely result.
173
174 Reference counting information is usually maintained by smart
175 pointer classes Ref, however this mechanism can be
176 supplemented or replaced by directly using the public
177 interface to RefCount.
178
179 The unmanage() member is only needed for special cases where memory
180 management must be turned off. For example, if a reference counted
181 object is created on the stack, memory management mechanisms based on
182 reference counting must be prohibited from deleting it. The unmanage()
183 member accomplishes this, but a better solution would be to allocate
184 the object on the heap with new and let a smart pointer manage the
185 memory for the object.
186
187 When using a debugger to look at reference counted objects the count is
188 maintained in the _reference_count_ member. However, this member is
189 encoded so that memory overwrites can be sometimes detected. Thus,
190 interpretation of _reference_count_ is not always straightforward.
191
192*/
193
194class RefCount: public Identity {
195 private:
196#if REF_MANAGE
197# define REF_MAX_NREF (UINT_MAX - 1)
198# define REF_MANAGED_CODE UINT_MAX
199#else
200# define REF_MAX_NREF UINT_MAX
201#endif
202 unsigned int _reference_count_;
203#if REF_USE_LOCKS
204 unsigned char ref_lock_;
205#endif
206
207 void error(const char*) const;
208 void too_many_refs() const;
209 void not_enough_refs() const;
210 protected:
211 RefCount(): _reference_count_(0) {
212 __REF_INITLOCK__();
213 //std::cout << "ref_lock_ = " << (int) ref_lock_ << std::endl;
214 }
215 RefCount(const RefCount&): _reference_count_(0) {
216 __REF_INITLOCK__();
217 //std::cout << "ref_lock_ = " << (int) ref_lock_ << std::endl;
218 }
219
220 // Assigment should not overwrite the reference count.
221 RefCount& operator=(const RefCount&) { return *this; }
222 public:
223 virtual ~RefCount();
224
225 /// Lock this object.
226 int lock_ptr() const;
227 /// Unlock this object.
228 int unlock_ptr() const;
229
230 /// start and stop using locks on this object
231 void use_locks(bool inVal);
232
233 /// Return the reference count.
234 refcount_t nreference() const {
235# if REF_MANAGE
236 if (!managed()) return 1;
237# endif
238 return _reference_count_;
239 }
240
241 /// Increment the reference count and return the new count.
242 refcount_t reference() {
243# if REF_MANAGE
244 if (!managed()) return 1;
245# endif
246 __REF_LOCK__(this);
247# if REF_CHECK_MAX_NREF
248 if (_reference_count_ >= REF_MAX_NREF) too_many_refs();
249# endif
250 _reference_count_++;
251 refcount_t r = _reference_count_;
252 __REF_UNLOCK__(this);
253 return r;
254 }
255
256 /// Decrement the reference count and return the new count.
257 refcount_t dereference() {
258# if REF_MANAGE
259 if (!managed()) return 1;
260# endif
261 __REF_LOCK__(this);
262# if REF_CHECK_MIN_NREF
263 if (_reference_count_ == 0) not_enough_refs();
264# endif
265 _reference_count_--;
266 refcount_t r = _reference_count_;
267 __REF_UNLOCK__(this);
268 return r;
269 }
270
271#if REF_MANAGE
272 int managed() const {
273 return _reference_count_ != REF_MANAGED_CODE;
274 }
275 /** Turn off the reference counting mechanism for this object.
276 The value returned by nreference() will always be
277 1 after this is called. The ability to unmanage()
278 objects must be turned on at compile time by defining
279 REF_MANAGE. There is a slight performance penalty. */
280 void unmanage() {
281 _reference_count_ = REF_MANAGED_CODE;
282 }
283#else // REF_MANAGE
284 /// Return 1 if the object is managed. Otherwise return 0.
285 int managed() const { return 1; }
286#endif // REF_MANAGE
287};
288
289/** Provides a few utility routines common to all
290 Ref template instantiations.
291*/
292class RefBase {
293 protected:
294 /// Print a warning message.
295 void warn ( const char * msg) const;
296 /// Called when stack data is referenced.
297 void warn_ref_to_stack() const;
298 /// Called when the deletion of stack data is skipped.
299 void warn_skip_stack_delete() const;
300 /// Called when the reference count is corrupted.
301 void warn_bad_ref_count() const;
302 /// Print information about the reference.
303 void ref_info(RefCount*p,std::ostream& os) const;
304 void ref_info(std::ostream& os) const;
305 void check_pointer() const;
306 void reference(RefCount *);
307 int dereference(RefCount *);
308 public:
309 RefBase() {};
310 virtual ~RefBase();
311 /// Returns the DescribedClass pointer for the contained object.
312 virtual RefCount* parentpointer() const = 0;
313 /** Requires that a nonnull reference is held. If not,
314 the program will abort. */
315 void require_nonnull() const;
316};
317
318/** A template class that maintains references counts.
319
320 Several of these operations can cause a reference to an object to be
321 replaced by a reference to a different object. If a reference to a
322 nonnull object is eliminated, the object's reference count is
323 decremented and the object is deleted if the reference count becomes
324 zero.
325
326 There also may be a to convert to T*, where T is the type of the object
327 which Ref references. Some compilers have bugs that prevent the use of
328 operator T*(). The pointer() member should be used instead.
329
330*/
331template <class T>
332class Ref : public RefBase {
333 private:
334 T* p;
335 public:
336 /// Create a reference to a null object.
337 Ref(): p(0) {}
338 /// Create a reference to the object a.
339 Ref(T*a) : p(0)
340 {
341 if (a) {
342 p = a;
343 reference(p);
344 }
345 }
346 /// Create a reference to the object referred to by a.
347 Ref(const Ref<T> &a) : p(0)
348 {
349 if (a.pointer()) {
350 p = a.pointer();
351 reference(p);
352 }
353 }
354 /// Create a reference to the object referred to by a.
355 template <class A> Ref(const Ref<A> &a): p(0)
356 {
357 if (a.pointer()) {
358 p = a.pointer();
359 reference(p);
360 }
361 }
362// /** Create a reference to the object a. Do a
363// dynamic_cast to convert a to the appropiate type. */
364// Ref(const RefBase&a) {
365// p = dynamic_cast<T*>(a.parentpointer());
366// reference(p);
367// }
368// /** Create a reference to the object a. Do a
369// dynamic_cast to convert a to the appropiate type. */
370// Ref(RefCount*a): p(0) {
371// operator<<(a);
372// }
373 /** Delete this reference to the object. Decrement the object's reference
374 count and delete the object if the count is zero. */
375 ~Ref()
376 {
377 clear();
378 }
379 /** Returns the reference counted object. The behaviour is undefined if
380 the object is null. */
381 T* operator->() const { return p; }
382 /// Returns a pointer the reference counted object.
383 T* pointer() const { return p; }
384 /// Implements the parentpointer pure virtual in the base class.
385 RefCount *parentpointer() const { return p; }
386
387 operator T*() const { return p; }
388 /** Returns a C++ reference to the reference counted object.
389 The behaviour is undefined if the object is null. */
390 T& operator *() const { return *p; };
391 /** Return 1 if this is a reference to a null object. Otherwise
392 return 0. */
393 int null() const { return p == 0; }
394 /// Return !null().
395 int nonnull() const { return p != 0; }
396 /** A variety of ordering and equivalence operators are provided using
397 the Identity class. */
398 template <class A> int operator==(const Ref<A>&a) const
399 { return eq(p,a.pointer()); }
400 template <class A> int operator>=(const Ref<A>&a) const
401 { return ge(p,a.pointer()); }
402 template <class A> int operator<=(const Ref<A>&a) const
403 { return le(p,a.pointer()); }
404 template <class A> int operator>(const Ref<A>&a) const
405 { return gt(p,a.pointer()); }
406 template <class A> int operator<(const Ref<A>&a) const
407 { return lt(p,a.pointer()); }
408 template <class A> int operator!=(const Ref<A>&a) const
409 { return ne(p,a.pointer()); }
410 /** Compare two objects returning -1, 0, or 1. Similar
411 to the C library routine strcmp. */
412 int compare(const Ref<T> &a) const {
413 return eq(p,a.p)?0:((lt(p,a.p)?-1:1));
414 }
415 /// Refer to the null object.
416 void clear()
417 {
418 if (p) {
419 int ref = dereference(p);
420 if (ref == 0)
421 delete p;
422 p = 0;
423 }
424 }
425 /// Assignment to c.
426 Ref<T>& operator=(const Ref<T> & c)
427 {
428 T *cp = c.pointer();
429 if (cp) {
430 cp->reference();
431 clear();
432 p=cp;
433 }
434 else {
435 clear();
436 }
437 return *this;
438 }
439 /// Assignment to c.
440 template <class A> Ref<T>& operator=(const Ref<A> & c)
441 {
442 A *cp = c.pointer();
443 if (cp) {
444 cp->reference();
445 clear();
446 p=cp;
447 }
448 else {
449 clear();
450 }
451 return *this;
452 }
453 /// Assignment to the object that a references using dynamic_cast.
454 Ref<T>& operator<<(const RefBase&a) {
455 T* cr = dynamic_cast<T*>(a.parentpointer());
456 if (cr) {
457 reference(cr);
458 clear();
459 }
460 p = cr;
461 return *this;
462 }
463 /** Assigns to the given base class pointer using dynamic_cast. If
464 the dynamic_cast fails and the argument is nonnull and has a
465 reference count of zero, then it is deleted. */
466 Ref<T>& operator<<(RefCount *a) {
467 T* cr = dynamic_cast<T*>(a);
468 if (cr) assign_pointer(cr);
469 else if (a && a->nreference() <= 0) delete a;
470 return *this;
471 }
472 /// Assignment to cr.
473 Ref<T>& operator=(T* cr)
474 {
475 assign_pointer(cr);
476 return *this;
477 }
478 /// Assignment to cr.
479 void assign_pointer(T* cr)
480 {
481 if (cr) {
482 if (DO_REF_CHECK_STACK(cr)) {
483 DO_REF_UNMANAGE(cr);
484 warn_ref_to_stack();
485 }
486 cr->reference();
487 }
488 clear();
489 p = cr;
490 }
491 /// Check the validity of the pointer.
492 void check_pointer() const
493 {
494 if (p && p->nreference() <= 0) {
495 warn_bad_ref_count();
496 }
497 }
498 /// Print information about the reference to os.
499 void ref_info(std::ostream& os) const
500 {
501 RefBase::ref_info(p,os);
502 }
503 /// Print a warning concerning the reference.
504 void warn(const char*s) const { RefBase::warn(s); }
505};
506
507}
508
509#endif
510
511// ///////////////////////////////////////////////////////////////////////////
512
513// Local Variables:
514// mode: c++
515// c-file-style: "CLJ"
516// End:
Note: See TracBrowser for help on using the repository browser.