xref: /titanic_41/usr/src/cmd/lms/SyncLib/Include/SPtr.h (revision 2f172c55ef76964744bc62b4500ece87f3089b4d)
1 /*******************************************************************************
2  * Copyright (C) 2004-2008 Intel Corp. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *  - Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  *
10  *  - Redistributions in binary form must reproduce the above copyright notice,
11  *    this list of conditions and the following disclaimer in the documentation
12  *    and/or other materials provided with the distribution.
13  *
14  *  - Neither the name of Intel Corp. nor the names of its
15  *    contributors may be used to endorse or promote products derived from this
16  *    software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS
22  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *******************************************************************************/
30 
31 //////////////////////////////////////////////////////////////////////////
32 //  SPtr.h
33 //
34 //  This is a smart pointer class. It receives an initialized object in
35 //  the constructor, and maintains a reference count to this object. It
36 //  deletes the object only when the reference count reaches 0.
37 //
38 //////////////////////////////////////////////////////////////////////////
39 
40 #ifndef _SPTR_H_
41 #define _SPTR_H_
42 
43 #include <memory>
44 #include "Semaphore.h"
45 
46 template
47 <class T>
48 class SPtr
49 {
50 public:
51 	// constructor
52 	explicit SPtr(T *ptr_p = 0) :
53 		_ptr(ptr_p),
54 		_pref_count(new int(1)),
55 		_psem(new Semaphore(1)) {}
56 
57 	// copy constructor
58 	template<class X>
59 	SPtr(const SPtr<X> &other_sptr_p)
60 	{
61 		other_sptr_p.getSem()->acquire();
62 		_ptr = other_sptr_p.get();
63 		_pref_count = other_sptr_p.getRefcnt();
64 		_psem = other_sptr_p.getSem();
65 		++(*_pref_count);
66 		_psem->release();
67 	}
68 
69 	SPtr(const SPtr &other_sptr_p)
70 	{
71 		other_sptr_p.getSem()->acquire();
72 		_ptr = other_sptr_p.get();
73 		_pref_count = other_sptr_p.getRefcnt();
74 		_psem = other_sptr_p.getSem();
75 		++(*_pref_count);
76 		_psem->release();
77 	}
78 
79 	// destructor
80 	~SPtr()
81 	{
82 		_psem->acquire();
83 		if (--(*_pref_count) == 0) {
84 			// delete pointer only on last destruction
85 			delete _pref_count;
86 			delete _psem;
87 			if (_ptr) {
88 				delete _ptr;
89 			}
90 			_ptr = 0;
91 		} else {
92 			_psem->release();
93 		}
94 	}
95 
96 	// operator=
97 	// if 'this' already points to an object, unreference it
98 	template<class X>
99 	SPtr &operator= (const SPtr<X> &other_sptr_p)
100 	{
101 		if ((void *)&other_sptr_p == this) {
102 			return *this;
103 		}
104 		_psem->acquire();
105 		if (--(*_pref_count) == 0) {
106 			delete _pref_count;
107 			delete _psem;
108 			if (_ptr) {
109 				delete _ptr;
110 			}
111 		} else {
112 			_psem->release();
113 		}
114 		other_sptr_p.getSem()->acquire();
115 		_ptr = (T *)other_sptr_p.get();
116 		_pref_count = other_sptr_p.getRefcnt();
117 		_psem = other_sptr_p.getSem();
118 		++(*_pref_count);
119 		_psem->release();
120 		return *this;
121 	}
122 
123 	SPtr &operator=(const SPtr &other_sptr_p)
124 	{
125 		if (&other_sptr_p == this) {
126 			return *this;
127 		}
128 		_psem->acquire();
129 		if (--(*_pref_count) == 0) {
130 			delete _pref_count;
131 			delete _psem;
132 			if (_ptr) {
133 				delete _ptr;
134 			}
135 		} else {
136 			_psem->release();
137 		}
138 		other_sptr_p.getSem()->acquire();
139 		_ptr = other_sptr_p.get();
140 		_pref_count = other_sptr_p.getRefcnt();
141 		_psem = other_sptr_p.getSem();
142 		++(*_pref_count);
143 		_psem->release();
144 		return *this;
145 	}
146 
147 	// operator*
148 	T &operator*() const
149 	{
150 		return *_ptr;
151 	}
152 
153 	// operator->
154 	T *operator->() const
155 	{
156 		return _ptr;
157 	}
158 
159 	// get - return inner pointer
160 	T *get() const
161 	{
162 		return _ptr;
163 	}
164 
165 	int *getRefcnt() const
166 	{
167 		return _pref_count;
168 	}
169 
170 	Semaphore *getSem() const
171 	{
172 		return _psem;
173 	}
174 
175 private:
176 	// the pointer itself
177 	T *_ptr;
178 	// a pointer to the reference count
179 	int *_pref_count;
180 	Semaphore *_psem;
181 } ;
182 
183 template
184 <class T>
185 inline bool operator==(const SPtr<T> &x, const SPtr<T> &y) {
186 	return(x.get() == y.get());
187 }
188 
189 template
190 <class T>
191 inline bool operator!=(const SPtr<T> &x, const SPtr<T> &y) {
192 	return(x.get() != y.get());
193 }
194 
195 #endif // _SPTR_H_
196 
197