MPQC 3.0.0-alpha
Loading...
Searching...
No Matches
ref.h
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// <mpqc_config.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#ifndef _util_ref_ref_h
73#define _util_ref_ref_h
74
75#include <iostream>
76#include <stdlib.h>
77#include <limits.h>
78#include <cassert>
79#include <util/misc/assert.h>
80
81#ifdef HAVE_CONFIG_H
82#include <mpqc_config.h>
83#endif
84
85#ifdef REF_OPTIMIZE
86#ifndef REF_CHECK_STACK
87# define REF_CHECK_STACK 0
88#endif
89#ifndef REF_MANAGE
90# define REF_MANAGE 0
91#endif
92#ifndef REF_CHECK_MAX_NREF
93# define REF_CHECK_MAX_NREF 0
94#endif
95#ifndef REF_CHECK_MIN_NREF
96# define REF_CHECK_MIN_NREF 0
97#endif
98#endif
99
100#ifdef SUNMOS
101#ifndef REF_CHECK_STACK
102#define REF_CHECK_STACK 0
103#endif
104#else
105#ifndef REF_CHECK_STACK
106#define REF_CHECK_STACK 0
107#endif
108#endif
109
110#ifndef REF_MANAGE
111#define REF_MANAGE 1
112#endif
113
114#ifndef REF_CHECK_MAX_NREF
115#define REF_CHECK_MAX_NREF 1
116#endif
117
118#ifndef REF_CHECK_MIN_NREF
119#define REF_CHECK_MIN_NREF 1
120#endif
121
122#ifndef REF_USE_LOCKS
123#if HAVE_STHREAD || HAVE_CREATETHREAD || HAVE_PTHREAD
124#define REF_USE_LOCKS 1
125#endif
126#else // REF_USE_LOCKS
127#warning "REF_USE_LOCKS not defined"
128#endif
129
130#ifndef REF_ALWAYS_USE_LOCKS
131#define REF_ALWAYS_USE_LOCKS 1
132#endif
133
134#if REF_CHECK_STACK
135#include <unistd.h>
136#ifndef HAVE_SBRK_DEC
137extern "C" void * sbrk(ssize_t);
138#endif
139#define DO_REF_CHECK_STACK(p) (((void*) (p) > sbrk(0)) && (p)->managed())
140#else // REF_CHECK_STACK
141#define DO_REF_CHECK_STACK(p) (0)
142#endif // REF_CHECK_STACK
143
144#if REF_MANAGE
145#define DO_REF_UNMANAGE(p) ((p)->unmanage())
146#else // REF_MANAGE
147#define DO_REF_UNMANAGE(p)
148#endif // REF_MANAGE
149
150#if REF_USE_LOCKS
151#define __REF_LOCK__(p) p->lock_ptr()
152#define __REF_UNLOCK__(p) p->unlock_ptr()
153#if REF_ALWAYS_USE_LOCKS
154#define __REF_INITLOCK__() use_locks(true)
155#else
156#define __REF_INITLOCK__() ref_lock_ = 0xff
157#endif
158#else
159#define __REF_LOCK__(p)
160#define __REF_UNLOCK__(p)
161#define __REF_INITLOCK__()
162#endif
163
164namespace sc {
165
166typedef unsigned long refcount_t;
167
192class RefCount {
193 private:
194#if REF_MANAGE
195# define REF_MAX_NREF (UINT_MAX - 1)
196# define REF_MANAGED_CODE UINT_MAX
197#else
198# define REF_MAX_NREF UINT_MAX
199#endif
200 unsigned int _reference_count_;
201#if REF_USE_LOCKS
202 unsigned char ref_lock_;
203#endif
204
205 void error(const char*) const;
206 void too_many_refs() const;
207 void not_enough_refs() const;
208 protected:
209 RefCount(): _reference_count_(0) {
210 __REF_INITLOCK__();
211 //std::cout << "ref_lock_ = " << (int) ref_lock_ << std::endl;
212 }
213 RefCount(const RefCount&): _reference_count_(0) {
214 __REF_INITLOCK__();
215 //std::cout << "ref_lock_ = " << (int) ref_lock_ << std::endl;
216 }
217
218 // Assigment should not overwrite the reference count.
219 RefCount& operator=(const RefCount&) { return *this; }
220 public:
221 virtual ~RefCount();
222
252 size_t identifier() const { return reinterpret_cast<const size_t>(this); }
253
255 int lock_ptr() const;
257 int unlock_ptr() const;
258
260 void use_locks(bool inVal);
261
263 refcount_t nreference() const {
264# if REF_MANAGE
265 if (!managed()) return 1;
266# endif
267 return _reference_count_;
268 }
269
271 refcount_t reference() {
272# if REF_MANAGE
273 if (!managed()) return 1;
274# endif
275 __REF_LOCK__(this);
276# if REF_CHECK_MAX_NREF
277 if (_reference_count_ >= REF_MAX_NREF) too_many_refs();
278# endif
279 _reference_count_++;
280 refcount_t r = _reference_count_;
281 __REF_UNLOCK__(this);
282 return r;
283 }
284
286 refcount_t dereference() {
287# if REF_MANAGE
288 if (!managed()) return 1;
289# endif
290 __REF_LOCK__(this);
291# if REF_CHECK_MIN_NREF
292 if (_reference_count_ == 0) not_enough_refs();
293# endif
294 _reference_count_--;
295 refcount_t r = _reference_count_;
296 __REF_UNLOCK__(this);
297 return r;
298 }
299
300#if REF_MANAGE
301 int managed() const {
302 return _reference_count_ != REF_MANAGED_CODE;
303 }
309 void unmanage() {
310 _reference_count_ = REF_MANAGED_CODE;
311 }
312#else // REF_MANAGE
314 int managed() const { return 1; }
315#endif // REF_MANAGE
316};
317
321class RefBase {
322 protected:
324 void warn ( const char * msg) const;
326 void warn_ref_to_stack() const;
330 void warn_bad_ref_count() const;
332 void ref_info(RefCount*p,std::ostream& os) const;
333 void ref_info(std::ostream& os) const;
334 void check_pointer() const;
335 void reference(RefCount *);
336 int dereference(RefCount *);
337 public:
338 RefBase() {};
339 virtual ~RefBase();
341 virtual RefCount* parentpointer() const = 0;
344 void require_nonnull() const;
345};
346
360template <class T>
361class Ref : public RefBase {
362 public:
363 typedef T element_type;
364 private:
365 T* p;
366 public:
368 Ref(): p(0) {}
370 Ref(T*a) : p(0)
371 {
372 if (a) {
373 p = a;
374 reference(p);
375 }
376 }
378 Ref(const Ref<T> &a) : p(0)
379 {
380 if (a.pointer()) {
381 p = a.pointer();
382 reference(p);
383 }
384 }
386 template <class A> Ref(const Ref<A> &a): p(0)
387 {
388 if (a.pointer()) {
389 p = a.pointer();
390 reference(p);
391 }
392 }
393// /** Create a reference to the object a. Do a
394// dynamic_cast to convert a to the appropiate type. */
395// Ref(const RefBase&a) {
396// p = dynamic_cast<T*>(a.parentpointer());
397// reference(p);
398// }
399// /** Create a reference to the object a. Do a
400// dynamic_cast to convert a to the appropiate type. */
401// Ref(RefCount*a): p(0) {
402// operator<<(a);
403// }
407 {
408 clear();
409 }
411 T* operator->() const { MPQC_ASSERT(p!=0); return p; }
413 T* pointer() const { return p; }
415 RefCount *parentpointer() const { return p; }
416
417 operator T*() const { return p; }
420 T& operator *() const { MPQC_ASSERT(p!=0); return *p; };
423 bool null() const { return p == 0; }
424 bool operator!() const {
425 return null();
426 }
427
428
433 template <class A> int operator==(const Ref<A>&a) const
434 {
435 // If both pointers are 0 then they are equal
436 if(p == 0 && a.pointer() == 0){
437 return 1;
438 }
439 // If one pointer is 0 and the other is not then they are different
440 else if((p != 0 && a.pointer() == 0) || (p == 0 && a.pointer() != 0)){
441 return 0;
442 }
443 // If both pointers are not 0 then we need to check the identifiers.
444 else{
445 return p->identifier() == a->identifier();
446 }
447 }
448
449 template <class A> int operator>=(const Ref<A>&a) const
450 {
451 // If both pointers are 0 then they are equal
452 if(p == 0 && a.pointer() == 0){
453 return 1;
454 }
455 // If p != 0 and a.p == 0 then the one that exists (p) is greater
456 else if((p != 0 && a.pointer() == 0)){
457 return 1;
458 }
459 // If p == 0 and a.p != 0 then the one that exists (a.p) is greater
460 else if((p == 0 && a.pointer() != 0)){
461 return 0;
462 }
463 // If both pointers are not 0 then we need to check the identifiers.
464 else{
465 return p->identifier() >= a->identifier();
466 }
467 }
468
469 template <class A> int operator<=(const Ref<A>&a) const
470 {
471 // If both pointers are 0 then they are equal
472 if(p == 0 && a.pointer() == 0){
473 return 1;
474 }
475 // If p != 0 and a.p == 0 then the one that exists (p) is greater
476 else if((p != 0 && a.pointer() == 0)){
477 return 0;
478 }
479 // If p == 0 and a.p != 0 then the one that exists (a.p) is greater
480 else if((p == 0 && a.pointer() != 0)){
481 return 1;
482 }
483 // If both pointers are not 0 then we need to check the identifiers.
484 else{
485 return p->identifier() <= a->identifier();
486 }
487 }
488
489 template <class A> int operator>(const Ref<A>&a) const
490 {
491 // If both pointers are 0 then they are equal
492 if(p == 0 && a.pointer() == 0){
493 return 0;
494 }
495 // If p != 0 and a.p == 0 then the one that exists (p) is greater
496 else if((p != 0 && a.pointer() == 0)){
497 return 1;
498 }
499 // If p == 0 and a.p != 0 then the one that exists (a.p) is greater
500 else if((p == 0 && a.pointer() != 0)){
501 return 0;
502 }
503 // If both pointers are not 0 then we need to check the identifiers.
504 else{
505 return p->identifier() > a->identifier();
506 }
507 }
508
509 template <class A> int operator<(const Ref<A>&a) const
510 {
511 // If both pointers are 0 then they are equal
512 if(p == 0 && a.pointer() == 0){
513 return 0;
514 }
515 // If p != 0 and a.p == 0 then the one that exists (p) is greater
516 else if((p != 0 && a.pointer() == 0)){
517 return 0;
518 }
519 // If p == 0 and a.p != 0 then the one that exists (a.p) is greater
520 else if((p == 0 && a.pointer() != 0)){
521 return 1;
522 }
523 // If both pointers are not 0 then we need to check the identifiers.
524 else{
525 return p->identifier() < a->identifier();
526 }
527 }
528
529 template <class A> int operator!=(const Ref<A>&a) const
530 {
531 // If both pointers are 0 then equal
532 if(p == 0 && a.pointer() == 0){
533 return 0;
534 }
535 // If one pointer is 0 and one is not then they are not equal
536 else if((p != 0 && a.pointer() == 0) || (p == 0 && a.pointer() != 0)){
537 return 1;
538 }
539 // If both pointers are not 0 then check id.
540 else{
541 return p->identifier() != a->identifier();
542 }
543 }
546 int compare(const Ref<T> &a) const {
547 return (p->identifier() == a->identifier())?0:(((p->identifier() < a->identifier())?-1:1));
548 }
550 void clear()
551 {
552 if (p) {
553 int ref = dereference(p);
554 if (ref == 0)
555 delete p;
556 p = 0;
557 }
558 }
561 {
562 T *cp = c.pointer();
563 if (cp) {
564 cp->reference();
565 clear();
566 p=cp;
567 }
568 else {
569 clear();
570 }
571 return *this;
572 }
574 template <class A> Ref<T>& operator=(const Ref<A> & c)
575 {
576 A *cp = c.pointer();
577 if (cp) {
578 cp->reference();
579 clear();
580 p=cp;
581 }
582 else {
583 clear();
584 }
585 return *this;
586 }
588 Ref<T>& operator<<(const RefBase&a) {
589 T* cr = dynamic_cast<T*>(a.parentpointer());
590 if (cr) {
591 reference(cr);
592 clear();
593 }
594 p = cr;
595 return *this;
596 }
600 Ref<T>& operator<<(RefCount *a) {
601 T* cr = dynamic_cast<T*>(a);
602 if (cr) assign_pointer(cr);
603 else if (a && a->nreference() <= 0) delete a;
604 return *this;
605 }
608 {
609 assign_pointer(cr);
610 return *this;
611 }
613 void assign_pointer(T* cr)
614 {
615 if (cr) {
616 if (DO_REF_CHECK_STACK(cr)) {
617 DO_REF_UNMANAGE(cr);
619 }
620 cr->reference();
621 }
622 clear();
623 p = cr;
624 }
626 void check_pointer() const
627 {
628 if (p && p->nreference() <= 0) {
630 }
631 }
633 void ref_info(std::ostream& os) const
634 {
635 RefBase::ref_info(p,os);
636 }
638 void warn(const char*s) const { RefBase::warn(s); }
639
641 bool nonnull() const { return !null(); }
642
643 protected:
644};
645
646template <class T>
647std::ostream&
648operator<<(std::ostream& os, const Ref<T>& r) {
649 r.ref_info(os);
650 return os;
651}
652
658template <typename T, typename EqualTo = std::equal_to<T> >
660 bool operator()(const Ref<T>& obj1, const Ref<T>& obj2) {
661 EqualTo equal_functor;
662 return equal_functor(*obj1,*obj2);
663 }
664};
665
666}
667
668#endif
669
670// ///////////////////////////////////////////////////////////////////////////
671
672// Local Variables:
673// mode: c++
674// c-file-style: "CLJ"
675// End:
Provides a few utility routines common to all Ref template instantiations.
Definition ref.h:321
void warn_skip_stack_delete() const
Called when the deletion of stack data is skipped.
void require_nonnull() const
Requires that a nonnull reference is held.
virtual RefCount * parentpointer() const =0
Returns the DescribedClass pointer for the contained object.
void warn(const char *msg) const
Print a warning message.
void warn_ref_to_stack() const
Called when stack data is referenced.
void warn_bad_ref_count() const
Called when the reference count is corrupted.
void ref_info(RefCount *p, std::ostream &os) const
Print information about the reference.
The base class for all reference counted objects.
Definition ref.h:192
refcount_t reference()
Increment the reference count and return the new count.
Definition ref.h:271
int unlock_ptr() const
Unlock this object.
int lock_ptr() const
Lock this object.
refcount_t nreference() const
Return the reference count.
Definition ref.h:263
int managed() const
Return 1 if the object is managed. Otherwise return 0.
Definition ref.h:314
size_t identifier() const
Return the unique identifier for this object that can be compared for different objects of different ...
Definition ref.h:252
refcount_t dereference()
Decrement the reference count and return the new count.
Definition ref.h:286
void use_locks(bool inVal)
start and stop using locks on this object
A template class that maintains references counts.
Definition ref.h:361
T & operator*() const
Returns a C++ reference to the reference counted object.
Definition ref.h:420
Ref< T > & operator<<(const RefBase &a)
Assignment to the object that a references using dynamic_cast.
Definition ref.h:588
void ref_info(std::ostream &os) const
Print information about the reference to os.
Definition ref.h:633
Ref()
Create a reference to a null object.
Definition ref.h:368
void assign_pointer(T *cr)
Assignment to cr.
Definition ref.h:613
T * pointer() const
Returns a pointer the reference counted object.
Definition ref.h:413
bool nonnull() const
Return !null().
Definition ref.h:641
RefCount * parentpointer() const
Implements the parentpointer pure virtual in the base class.
Definition ref.h:415
Ref(const Ref< T > &a)
Create a reference to the object referred to by a.
Definition ref.h:378
Ref(T *a)
Create a reference to the object a.
Definition ref.h:370
Ref< T > & operator=(const Ref< T > &c)
Assignment to c.
Definition ref.h:560
T * operator->() const
Returns the reference counted object.
Definition ref.h:411
void clear()
Refer to the null object.
Definition ref.h:550
void warn(const char *s) const
Print a warning concerning the reference.
Definition ref.h:638
void check_pointer() const
Check the validity of the pointer.
Definition ref.h:626
~Ref()
Create a reference to the object a.
Definition ref.h:406
int compare(const Ref< T > &a) const
Compare two objects returning -1, 0, or 1.
Definition ref.h:546
Ref< T > & operator=(T *cr)
Assignment to cr.
Definition ref.h:607
Ref(const Ref< A > &a)
Create a reference to the object referred to by a.
Definition ref.h:386
bool null() const
Return true if this is a reference to a null object.
Definition ref.h:423
int operator==(const Ref< A > &a) const
Ordering and equivalence operators are determined by the identifier if both pointers are not null.
Definition ref.h:433
std::vector< unsigned int > operator<<(const GaussianBasisSet &B, const GaussianBasisSet &A)
computes a map from basis functions in A to the equivalent basis functions in B.
Contains all MPQC code up to version 3.
Definition mpqcin.h:14
this functor can be used as a binary predicate for standard algorithms.
Definition ref.h:659

Generated at Wed Sep 25 2024 02:45:30 for MPQC 3.0.0-alpha using the documentation package Doxygen 1.12.0.