Edinburgh Speech Tools 2.4-release
EST_THandle.h
1 /************************************************************************/
2 /* */
3 /* Centre for Speech Technology Research */
4 /* University of Edinburgh, UK */
5 /* Copyright (c) 1996,1997 */
6 /* All Rights Reserved. */
7 /* */
8 /* Permission is hereby granted, free of charge, to use and distribute */
9 /* this software and its documentation without restriction, including */
10 /* without limitation the rights to use, copy, modify, merge, publish, */
11 /* distribute, sublicense, and/or sell copies of this work, and to */
12 /* permit persons to whom this work is furnished to do so, subject to */
13 /* the following conditions: */
14 /* 1. The code must retain the above copyright notice, this list of */
15 /* conditions and the following disclaimer. */
16 /* 2. Any modifications must be clearly marked as such. */
17 /* 3. Original authors' names are not deleted. */
18 /* 4. The authors' names are not used to endorse or promote products */
19 /* derived from this software without specific prior written */
20 /* permission. */
21 /* */
22 /* THE UNIVERSITY OF EDINBURGH AND THE CONTRIBUTORS TO THIS WORK */
23 /* DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING */
24 /* ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT */
25 /* SHALL THE UNIVERSITY OF EDINBURGH NOR THE CONTRIBUTORS BE LIABLE */
26 /* FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES */
27 /* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN */
28 /* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, */
29 /* ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF */
30 /* THIS SOFTWARE. */
31 /* */
32 /*************************************************************************/
33
34#ifndef __EST_THANDLE_H__
35#define __EST_THANDLE_H__
36
37#include <iostream>
38
39using namespace std;
40
41#include "EST_bool.h"
42
43/** A `smart' pointer which does reference counting.
44 *
45 * Behaves almost like a pointer as far as naive code is concerned, but
46 * keeps count of how many handles are holding on to the contents
47 * and deletes it when there are none.
48 *
49 * You need to be careful there are no dumb C++ pointers to things which
50 * are being handled this way.
51 *
52 * Things to be handled should implement the same interface as EST_Handleable
53 * (either by taking that as a superclass or by reimplementing it) and in
54 * addition define {\tt object_ptr()}. See EST_TBox for an example.
55 *
56 * There are two parameter types. In most cases the thing which contains the
57 * reference count and the data it represents will be the same object, but
58 * in the case of boxed values it may not be, so you can specify the type
59 * of both independently.
60 *
61 * @see EST_Handleable
62 * @see EST_TBox
63 * @see EST_THandle:example
64 *
65 * @author Richard Caley <rjc@cstr.ed.ac.uk>
66 * @version $Id: EST_THandle.h,v 1.5 2006/07/19 21:52:12 awb Exp $
67 */
68
69
70template<class BoxT, class ObjectT>
72
73private:
74 BoxT *ptr;
75
76public:
77
78 EST_THandle(void) { ptr = (BoxT *)NULL; }
79
80 EST_THandle(BoxT *p) { if ((ptr=p)) p->inc_refcount(); }
81
82 EST_THandle(const EST_THandle &cp) {
83 ptr=cp.ptr;
84 if (ptr)
85 ptr->inc_refcount();
86 }
87
88 ~EST_THandle(void) {
89 if (ptr)
90 ptr->dec_refcount();
91 if (ptr && ptr->is_unreferenced())
92 delete ptr;
93 }
94
95 bool null() const { return ptr == NULL; }
96
97 int shareing(void) const { return ptr?(ptr->refcount() > 1):0; }
98
99 EST_THandle &operator = (EST_THandle h) {
100 // doing it in this order means self assignment is safe.
101 if (h.ptr)
102 (h.ptr)->inc_refcount();
103 if (ptr)
104 ptr->dec_refcount();
105 if (ptr && ptr->is_unreferenced())
106 delete ptr;
107 ptr=h.ptr;
108 return *this;
109 }
110
111 // If they manage to get hold of one...
112 // Actually usually used to assign NULL and so (possibly) deallocate
113 // the object currently pointed to.
114 EST_THandle &operator = (BoxT *t_ptr) {
115 // doing it in this order means self assignment is safe.
116 if (t_ptr)
117 t_ptr->inc_refcount();
118 if (ptr)
119 ptr->dec_refcount();
120 if (ptr && ptr->is_unreferenced())
121 delete ptr;
122 ptr=t_ptr;
123 return *this;
124 }
125
126 operator ObjectT *() {
127 return ptr?(ptr->object_ptr()):(ObjectT *)NULL;
128 }
129
130 operator const ObjectT *() const {
131 return ptr?(ptr->object_ptr()):(const ObjectT *)NULL;
132 }
133
134
135 int operator == (const BoxT *p) const { return ptr == p; }
136 int operator != (const BoxT *p) const { return !(*this == p); }
137
138 const ObjectT& operator *() const { return *(ptr->object_ptr()); }
139 ObjectT& operator *() { return *(ptr->object_ptr()); }
140 const ObjectT* operator ->() const { return (ptr->object_ptr()); }
141 ObjectT* operator ->() { return (ptr->object_ptr()); }
142
143 friend int operator == (const EST_THandle< BoxT, ObjectT > &a, const EST_THandle< BoxT, ObjectT > & b)
144 {return a.ptr==b.ptr; }
145 friend int operator != (const EST_THandle< BoxT, ObjectT > &a, const EST_THandle< BoxT, ObjectT > & b)
146 { return !( a==b ); }
147
148 friend ostream & operator << (ostream &s, const EST_THandle< BoxT, ObjectT > &a)
149 { return s << "HANDLE"; }
150};
151
152#endif