InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
K2SmartPtr.h
1 //========================================================================================
2 //
3 // $File$
4 //
5 // Owner: Mat Marcus
6 //
7 // $Author$
8 //
9 // $DateTime$
10 //
11 // $Revision$
12 //
13 // $Change$
14 //
15 // Copyright 1997-2010 Adobe Systems Incorporated. All rights reserved.
16 //
17 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance
18 // with the terms of the Adobe license agreement accompanying it. If you have received
19 // this file from a source other than Adobe, then your use, modification, or
20 // distribution of it requires the prior written permission of Adobe.
21 //
22 //
23 // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. Permission to copy,
24 // use, modify, sell and distribute this software is granted provided this
25 // copyright notice appears in all copies. This software is provided "as is"
26 // without express or implied warranty, and with no claim as to its
27 // suitability for any purpose.
28 //
29 // Also based on Loki/SmartPtr.h
30 //
31 // The Loki Library
32 // Copyright (c) 2001 by Andrei Alexandrescu
33 // This code accompanies the book:
34 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design
35 // Patterns Applied". Copyright (c) 2001. Addison-Wesley.
36 // Permission to use, copy, modify, distribute and sell this software for any
37 // purpose is hereby granted without fee, provided that the above copyright
38 // notice appear in all copies and that both that copyright notice and this
39 // permission notice appear in supporting documentation.
40 // The author or Addison-Welsey Longman make no representations about the
41 // suitability of this software for any purpose. It is provided "as is"
42 // without express or implied warranty.
43 //
44 //========================================================================================
45 
46 #ifndef __K2SmartPtr__
47 #define __K2SmartPtr__
48 
49 #include <boost/config.hpp> // for broken compiler workarounds
50 #include <cstddef> // for std::size_t
51 #include <memory> // for std::auto_ptr
52 #include <algorithm> // for std::swap
53 #include <boost/utility.hpp> // for boost::noncopyable
54 #include <functional> // for std::less
55 
56 namespace K2 {
57 
58 // scoped_ptr --------------------------------------------------------------//
59 
71 template<typename T> class scoped_ptr : boost::noncopyable {
72  typedef scoped_ptr Self;
73  T* ptr;
74 
75 public:
76  typedef T element_type; // The type of the stored pointer
77 
83  explicit scoped_ptr( T* p=0 ) : ptr(p) {}
84 
88  ~scoped_ptr() { delete ptr; }
89 
94  void reset( T* p=0 ) { if ( ptr != p ) { delete ptr; ptr = p; } }
95 
102  T* release( ) { T* ret = ptr; ptr = nil; return ret; }
103 
109  T& operator*() const { return *ptr; }
110 
111 #ifdef BOOST_MSVC
112 #endif
113 
118  T* operator->() const { return ptr; }
119 #ifdef BOOST_MSVC
120 #endif
121 
125  T* get() const { return ptr; }
126 
127 
128  bool operator!() const // Enables "if (!sp) ..."
129  { return get() == 0; }
130 
131  inline friend bool operator==(const Self& lhs,
132  const T* rhs)
133  { return lhs.get() == rhs; }
134 
135  inline friend bool operator==(const T* lhs,
136  const Self& rhs)
137  { return rhs == lhs; }
138 
139  inline friend bool operator!=(const Self& lhs,
140  const T* rhs)
141  { return !(lhs == rhs); }
142 
143  inline friend bool operator!=(const T* lhs,
144  const Self& rhs)
145  { return rhs != lhs; }
146 
147 #if 0
148  private:
149  // Helper for enabling 'if (sp)'
150  class Tester
151  {
152  void operator delete(void*);
153  };
154 
155  public:
156  // enable 'if (sp)'
157  operator Tester*() const
158  {
159  if (!*this) return 0;
160  static Tester t;
161  return &t;
162  }
163 #else
164  operator void*() const {
165  return get();
166  }
167 #endif
168 
169  }; // scoped_ptr
170 
171 
172 // scoped_array ------------------------------------------------------------//
173 
186 template<typename T> class scoped_array : boost::noncopyable {
187 
188  T* ptr;
189 
190  public:
191  typedef T element_type;
192 
197  explicit scoped_array( T* p=0 ) : ptr(p) {}
198 
203  ~scoped_array() { delete [] ptr; }
204 
209  void reset( T* p=0 ) { if ( ptr != p ) {delete [] ptr; ptr=p;} }
210 
215  T* get() const { return ptr; }
216 
223  T* release( ) { T* ret = ptr; ptr = nil; return ret; }
224 
232  T& operator[](std::size_t i) const { return ptr[i]; }
233  }; // scoped_array
234 
235 // shared_array ------------------------------------------------------------//
236 
242 template<typename T> class shared_array {
243  typedef shared_array Self;
244  public:
245  typedef T element_type;
246  typedef object_type data_type;
247 
248  explicit shared_array(T* p =0) : px(p) {
249  pn = new long(1); // fix: prevent leak if new throws
250  }
251 
252  shared_array(const shared_array& r) : px(r.px)
253  { ++*(pn = r.pn); }
254 
255  ~shared_array() { dispose(); }
256 
257  shared_array& operator=(const shared_array& r) {
258  if (pn != r.pn) { // Q: why not px != r.px? A: fails when both px == 0
259  ++*r.pn; // done before dispose() in case r.pn transitively
260  // dependent on *this (bug reported by Thomas Maeder)
261  dispose();
262  px = r.px;
263  pn = r.pn;
264  }
265  return *this;
266  } // operator=
267 
272  void reset(T* p=0) {
273  if ( px == p ) return; // fix: self-assignment safe
274  if (--*pn == 0) { delete [] px; }
275  else { // allocate new reference counter
276  pn = new long; // fix: prevent leak if new throws
277  } // allocate new reference counter
278  *pn = 1;
279  px = p;
280  } // reset
281 
282  T* get() const { return px; }
283  T& operator[](std::size_t i) const { return px[i]; }
284 
289  long use_count() const { return *pn; }
290 
295  bool unique() const { return *pn == 1; }
296 
301  void swap(shared_array<T>& other)
302  { std::swap(px,other.px); std::swap(pn,other.pn); }
303 
304  bool operator!() const // Enables "if (!sp) ..."
305  { return get() == 0; }
306 
307  inline friend bool operator==(const Self& lhs,
308  const T* rhs)
309  { return lhs.get() == rhs; }
310 
311  inline friend bool operator==(const T* lhs,
312  const Self& rhs)
313  { return rhs == lhs; }
314 
315  inline friend bool operator!=(const Self& lhs,
316  const T* rhs)
317  { return !(lhs == rhs); }
318 
319  inline friend bool operator!=(const T* lhs,
320  const Self& rhs)
321  { return rhs != lhs; }
322 
323 #if 0
324  private:
325  // Helper for enabling 'if (sp)'
326  class Tester
327  {
328  void operator delete(void*);
329  };
330 
331  public:
332  // enable 'if (sp)'
333  operator Tester*() const
334  {
335  if (!*this) return 0;
336  static Tester t;
337  return &t;
338  }
339 #else
340  operator void*() const {
341  return get();
342  }
343 #endif
344  private:
345  T* px; // contained pointer
346  long* pn; // ptr to reference counter
347 
348  void dispose() { if (--*pn == 0) { delete [] px; delete pn; } }
349 
350  }; // shared_array
351 
352 template<typename T>
353  inline bool operator==(const shared_array<T>& a, const shared_array<T>& b)
354  { return a.get() == b.get(); }
355 
356 template<typename T>
357  inline bool operator!=(const shared_array<T>& a, const shared_array<T>& b)
358  { return a.get() != b.get(); }
359 
360 } // namespace K2
361 
362 
363 
364 // specializations for things in namespace std -----------------------------//
365 
366 #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
367 
368 namespace std {
369 
370 template<typename T>
371  inline void swap(K2::shared_array<T>& a, K2::shared_array<T>& b)
372  { a.swap(b); }
373 
374 // Specialize std::less so we can use shared pointers and arrays as keys in
375 // associative collections.
376 
377 // It's still a controversial question whether this is better than supplying
378 // a full range of comparison operators (<, >, <=, >=).
379 
380 template<typename T>
381  struct less< K2::shared_array<T> >
382  : function<bool(K2::shared_array<T>, K2::shared_array<T>) >
383  {
384  bool operator()(const K2::shared_array<T>& a,
385  const K2::shared_array<T>& b) const
386  { return less<T*>()(a.get(),b.get()); }
387  };
388 
389 } // namespace std
390 
391 #endif // ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
392 
393 #endif // __K2SmartPtr__
394 
395