source: trunk/libdjvu/GSmartPointer.h @ 280

Last change on this file since 280 was 280, checked in by rbri, 11 years ago

DJVU plugin: djvulibre updated to version 3.5.22

File size: 16.9 KB
Line 
1//C-  -*- C++ -*-
2//C- -------------------------------------------------------------------
3//C- DjVuLibre-3.5
4//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
5//C- Copyright (c) 2001  AT&T
6//C-
7//C- This software is subject to, and may be distributed under, the
8//C- GNU General Public License, either Version 2 of the license,
9//C- or (at your option) any later version. The license should have
10//C- accompanied the software or you may obtain a copy of the license
11//C- from the Free Software Foundation at http://www.fsf.org .
12//C-
13//C- This program is distributed in the hope that it will be useful,
14//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
15//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16//C- GNU General Public License for more details.
17//C-
18//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library from
19//C- Lizardtech Software.  Lizardtech Software has authorized us to
20//C- replace the original DjVu(r) Reference Library notice by the following
21//C- text (see doc/lizard2002.djvu and doc/lizardtech2007.djvu):
22//C-
23//C-  ------------------------------------------------------------------
24//C- | DjVu (r) Reference Library (v. 3.5)
25//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
26//C- | The DjVu Reference Library is protected by U.S. Pat. No.
27//C- | 6,058,214 and patents pending.
28//C- |
29//C- | This software is subject to, and may be distributed under, the
30//C- | GNU General Public License, either Version 2 of the license,
31//C- | or (at your option) any later version. The license should have
32//C- | accompanied the software or you may obtain a copy of the license
33//C- | from the Free Software Foundation at http://www.fsf.org .
34//C- |
35//C- | The computer code originally released by LizardTech under this
36//C- | license and unmodified by other parties is deemed "the LIZARDTECH
37//C- | ORIGINAL CODE."  Subject to any third party intellectual property
38//C- | claims, LizardTech grants recipient a worldwide, royalty-free,
39//C- | non-exclusive license to make, use, sell, or otherwise dispose of
40//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
41//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
42//C- | General Public License.   This grant only confers the right to
43//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
44//C- | the extent such infringement is reasonably necessary to enable
45//C- | recipient to make, have made, practice, sell, or otherwise dispose
46//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
47//C- | any greater extent that may be necessary to utilize further
48//C- | modifications or combinations.
49//C- |
50//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
51//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
52//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
53//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
54//C- +------------------------------------------------------------------
55//
56// $Id: GSmartPointer.h,v 1.16 2008/03/05 01:44:20 leonb Exp $
57// $Name: release_3_5_22 $
58
59#ifndef _GSMARTPOINTER_H_
60#define _GSMARTPOINTER_H_
61#ifdef HAVE_CONFIG_H
62#include "config.h"
63#endif
64#if NEED_GNUG_PRAGMAS
65# pragma interface
66#endif
67
68/** @name GSmartPointer.h
69
70    Files #"GSmartPointer.h"# and #"GSmartPointer.cpp"# define a smart-pointer
71    class which automatically performs thread-safe reference counting.  Class
72    \Ref{GP} implements smart-pointers by overloading the usual pointer
73    assignment and dereferencing operators. The overloaded operators maintain
74    the reference counters and destroy the pointed objects as soon as their
75    reference counter reaches zero.  Transparent type conversions are provided
76    between smart-pointers and regular pointers.  Objects referenced by
77    smart-pointers must be derived from class \Ref{GPEnabled}.
78
79    @memo
80    Thread-Safe reference counting smart-pointers.
81    @author
82    L\'eon Bottou <leonb@research.att.com> -- initial implementation\\
83    Andrei Erofeev <eaf@geocities.com> -- bug fix.
84
85// From: Leon Bottou, 1/31/2002
86// Class GPBuffer has been added (but not documented) by Lizardtech.
87// Our original implementation consisted of multiple classes.
88// <http://prdownloads.sourceforge.net/djvu/DjVu2_2b-src.tgz>.
89
90    @version
91    #$Id: GSmartPointer.h,v 1.16 2008/03/05 01:44:20 leonb Exp $#
92    @args
93*/
94//@{
95
96#if defined(_MSC_VER)
97// Language lawyer say MSVC6 is wrong on that one.
98// Cf section 5.4.7 in november 1997 draft.
99#pragma warning( disable : 4243 )
100#endif
101
102#include "DjVuGlobal.h"
103#include "atomic.h"
104
105#ifdef HAVE_NAMESPACES
106namespace DJVU {
107# ifdef NOT_DEFINED // Just to fool emacs c++ mode
108}
109#endif
110#endif
111
112
113
114/** Base class for reference counted objects. 
115    This is the base class for all reference counted objects.
116    Any instance of a subclass of #GPEnabled# can be used with
117    smart-pointers (see \Ref{GP}). 
118 */
119class DJVUAPI GPEnabled
120{
121  friend class GPBase;
122  void destroy();
123  void unref();
124  void ref();
125public:
126  /// Null constructor.
127  GPEnabled();
128  /// Copy construcotr
129  GPEnabled(const GPEnabled & obj);
130  /// Virtual destructor.
131  virtual ~GPEnabled();
132  /// Copy operator
133  GPEnabled & operator=(const GPEnabled & obj);
134  /** Returns the number of references to this object.  This should be only
135      used for debugging purposes. Other uses are not thread-safe. */
136  int get_count(void) const;
137protected:
138  /// The reference counter
139  volatile int count;
140};
141
142
143
144/** Base class for all smart-pointers.
145    This class implements common mechanisms for all
146    smart-pointers (see \Ref{GP}). There should be no need
147    to use this class directly.  Its sole purpose consists
148    in reducing the template expansion overhead.
149*/
150
151class DJVUAPI GPBase
152{
153public:
154  /** Null Constructor. */
155  GPBase();
156  /** Copy Constructor.
157      Increments the reference count.
158      @param sptr reference to a #GPBase# object. */
159  GPBase(const GPBase &sptr);
160  /** Construct a GPBase from a pointer.
161      Increments the reference count.
162      @param nptr pointer to a #GPEnabled# object. */
163  GPBase(GPEnabled *nptr);
164  /** Destructor. Decrements the reference count. */
165  ~GPBase();
166  /** Accesses the actual pointer. */
167  GPEnabled* get() const;
168  /** Assignment from smartpointer.
169      Increments the counter of the new value of the pointer.
170      Decrements the counter of the previous value of the pointer. */
171  GPBase& assign(const GPBase &sptr);
172  /** Assignment from pointer.
173      Checks that the object is not being destroyed.
174      Increments the counter of the new value of the pointer.
175      Decrements the counter of the previous value of the pointer. */
176  GPBase& assign(GPEnabled *nptr);
177  /** Assignment operator. */
178  GPBase & operator=(const GPBase & obj);
179  /** Comparison operator. */
180  int operator==(const GPBase & g2) const;
181protected:
182  /** Actual pointer */
183  GPEnabled *ptr;
184};
185
186
187/** Reference counting pointer.
188    Class #GP<TYPE># represents a smart-pointer to an object of type #TYPE#.
189    Type #TYPE# must be a subclass of #GPEnabled#.  This class overloads the
190    usual pointer assignment and dereferencing operators. The overloaded
191    operators maintain the reference counters and destroy the pointed object
192    as soon as their reference counter reaches zero.  Transparent type
193    conversions are provided between smart-pointers and regular pointers.
194
195    Using a smart-pointer is a convenience and not an obligation.  There is no
196    need to use a smart-pointer to access a #GPEnabled# object.  As long as
197    you never use a smart-pointer to access a #GPEnabled# object, its
198    reference counter remains zero.  Since the reference counter is never
199    decremented from one to zero, the object is never destroyed by the
200    reference counting code.  You can therefore choose to only use regular
201    pointers to access objects allocated on the stack (automatic variables) or
202    objects allocated dynamically.  In the latter case you must explicitly
203    destroy the dynamically allocated object with operator #delete#.
204
205    The first time you use a smart-pointer to access #GPEnabled# object, the
206    reference counter is incremented to one. Object destruction will then
207    happen automatically when the reference counter is decremented back to
208    zero (i.e. when the last smart-pointer referencing
209    this object stops doing so).
210    This will happen regardless of how many regular pointers
211    reference this object.
212    In other words, if you start using smart-pointers with a #GPEnabled#
213    object, you engage automatic mode for this object.  You should only do
214    this with objects dynamically allocated with operator #new#.  You should
215    never destroy the object yourself, but let the smart-pointers control the
216    life of the object.
217   
218    {\bf Performance considerations} --- Thread safe reference counting incurs
219    a significant overhead. Smart-pointer are best used with sizeable objects
220    for which the cost of maintaining the counters represent a small fraction
221    of the processing time.  It is always possible to cache a smart-pointer
222    into a regular pointer.  The cached pointer will remain valid until the
223    smart-pointer object is destroyed or the smart-pointer value is changed.
224
225    {\bf Safety considerations} --- As explained above, a #GPEnabled# object
226    switches to automatic mode as soon as it becomes referenced by a
227    smart-pointer.  There is no way to switch the object back to manual mode.
228    Suppose that you have decided to only use regular pointers with a
229    particular #GPEnabled# object.  You therefore plan to destroy the object
230    explicitly when you no longer need it.  When you pass a regular pointer to
231    this object as argument to a function, you really need to be certain that
232    the function implementation will not assign this pointer to a
233    smart-pointer.  Doing so would indeed destroy the object as soon as the
234    function returns.  The bad news is that the fact that a function assigns a
235    pointer argument to a smart-pointer does not necessarily appear in the
236    function prototype.  Such a behavior must be {\em documented} with the
237    function public interface.  As a convention, we usually write such
238    functions with smart-pointer arguments instead of a regular pointer
239    arguments.  This is not enough to catch the error at compile time, but
240    this is a simple way to document such a behavior.  We still believe that
241    this is a small problem in regard to the benefits of the smart-pointer.
242    But one has to be aware of its existence.  */
243
244template <class TYPE>
245class GP : protected GPBase
246{
247public:
248  /** Constructs a null smart-pointer. */
249  GP();
250  /** Constructs a copy of a smart-pointer.
251      @param sptr smart-pointer to copy. */
252  GP(const GP<TYPE> &sptr);
253  /** Constructs a smart-pointer from a regular pointer.
254      The pointed object must be dynamically allocated (with operator #new#).
255      You should no longer explicitly destroy the object referenced by #sptr#
256      since the object life is now controlled by smart-pointers. 
257      @param nptr regular pointer to a {\em dynamically allocated object}. */
258  GP(TYPE *nptr);
259  /** Converts a smart-pointer into a regular pointer. 
260      This is useful for caching the value of a smart-pointer for performances
261      purposes.  The cached pointer will remain valid until the smart-pointer
262      is destroyed or until the smart-pointer value is changed. */
263  operator TYPE* () const;
264  /** Assigns a regular pointer to a smart-pointer lvalue.
265      The pointed object must be dynamically allocated (with operator #new#).
266      You should no longer explicitly destroy the object referenced by #sptr#
267      since the object life is now controlled by smart-pointers. 
268      @param nptr regular pointer to a {\em dynamically allocated object}. */
269  GP<TYPE>& operator= (TYPE *nptr);
270  /** Assigns a smart-pointer to a smart-pointer lvalue.
271      @param sptr smart-pointer copied into this smart-pointer. */
272  GP<TYPE>& operator= (const GP<TYPE> &sptr);
273  /** Indirection operator.
274      This operator provides a convenient access to the members
275      of a smart-pointed object. Operator #-># works with smart-pointers
276      exactly as with regular pointers. */
277  TYPE* operator->() const;
278  /** Dereferencement operator.
279      This operator provides a convenient access to the smart-pointed object.
280      Operator #*# works with smart-pointers exactly as with regular pointers. */
281  TYPE& operator*() const;
282  /** Comparison operator.
283      Returns true if both this smart-pointer and pointer #nptr# point to the
284      same object.  The automatic conversion from smart-pointers to regular
285      pointers allows you to compare two smart-pointers as well. 
286      @param nptr pointer to compare with. */
287  int operator== (TYPE *nptr) const;
288  /** Comparison operator. 
289      Returns true if this smart-pointer and pointer #nptr# point to different
290      objects. The automatic conversion from smart-pointers to regular
291      pointers allows you to compare two smart-pointers as well. 
292      @param nptr pointer to compare with. */
293  int operator!= (TYPE *nptr) const;
294  /** Test operator.
295      Returns true if the smart-pointer is null.  The automatic conversion
296      from smart-pointers to regular pointers allows you to test whether
297      a smart-pointer is non-null.  You can use both following constructs:
298      \begin{verbatim}
299      if (gp) { ... }
300      while (! gp) { ... }
301      \end{verbatim} */
302  int operator! () const;
303};
304
305//@}
306
307// INLINE FOR GPENABLED
308
309inline
310GPEnabled::GPEnabled()
311  : count(0)
312{
313}
314
315inline
316GPEnabled::GPEnabled(const GPEnabled & obj) 
317  : count(0) 
318{
319
320}
321
322inline int
323GPEnabled::get_count(void) const
324{
325   return count;
326}
327
328inline GPEnabled & 
329GPEnabled::operator=(const GPEnabled & obj)
330{ 
331  /* The copy operator should do nothing because the count should not be
332     changed.  Subclasses of GPEnabled will call this version of the copy
333     operator as part of the default 'memberwise copy' strategy. */
334  return *this; 
335}
336
337inline void 
338GPEnabled::ref()
339{
340#if PARANOID_DEBUG
341  assert (count >= 0);
342#endif
343  atomicIncrement(&count);
344}
345
346inline void 
347GPEnabled::unref()
348{
349#if PARANOID_DEBUG
350  assert (count > 0);
351#endif
352  if (! atomicDecrement(&count))
353    destroy();
354}
355
356// INLINE FOR GPBASE
357
358inline
359GPBase::GPBase()
360  : ptr(0)
361{
362}
363
364inline
365GPBase::GPBase(GPEnabled *nptr)
366  : ptr(0)
367{
368  assign(nptr);
369}
370
371inline
372GPBase::GPBase(const GPBase &sptr)
373{
374  if (sptr.ptr)
375    sptr.ptr->ref();
376  ptr = sptr.ptr;
377}
378
379inline
380GPBase::~GPBase()
381{
382  GPEnabled *old = ptr;
383  ptr = 0;
384  if (old)
385    old->unref();
386}
387
388inline GPEnabled* 
389GPBase::get() const
390{
391#if PARANOID_DEBUG
392  if (ptr && ptr->get_count() <= 0)
393    *(int*)0=0;
394#endif
395  return ptr;
396}
397
398inline GPBase &
399GPBase::operator=(const GPBase & obj)
400{
401  return assign(obj);
402}
403
404inline int 
405GPBase::operator==(const GPBase & g2) const
406{
407  return ptr == g2.ptr;
408}
409
410
411
412
413// INLINE FOR GP<TYPE>
414
415template <class TYPE> inline
416GP<TYPE>::GP()
417{
418}
419
420template <class TYPE> inline
421GP<TYPE>::GP(TYPE *nptr)
422: GPBase((GPEnabled*)nptr)
423{
424}
425
426template <class TYPE> inline
427GP<TYPE>::GP(const GP<TYPE> &sptr)
428: GPBase((const GPBase&) sptr)
429{
430}
431
432template <class TYPE> inline
433GP<TYPE>::operator TYPE* () const
434{
435  return (TYPE*) ptr;
436}
437
438template <class TYPE> inline TYPE*
439GP<TYPE>::operator->() const
440{
441#if PARANOID_DEBUG
442  if (ptr && ptr->get_count() <= 0)
443    *(int*)0=0;
444#endif
445  return (TYPE*) ptr;
446}
447
448template <class TYPE> inline TYPE&
449GP<TYPE>::operator*() const
450{
451#if PARANOID_DEBUG
452  if (ptr && ptr->get_count() <= 0)
453    *(int*)0=0;
454#endif
455  return *(TYPE*) ptr;
456}
457
458template <class TYPE> inline GP<TYPE>& 
459GP<TYPE>::operator= (TYPE *nptr)
460{
461  return (GP<TYPE>&)( assign(nptr) );
462}
463
464template <class TYPE> inline GP<TYPE>& 
465GP<TYPE>::operator= (const GP<TYPE> &sptr)
466{
467  return (GP<TYPE>&)( assign((const GPBase&)sptr) );
468}
469
470template <class TYPE> inline int
471GP<TYPE>::operator== (TYPE *nptr) const
472{
473  return ( (TYPE*)ptr == nptr );
474}
475
476template <class TYPE> inline int
477GP<TYPE>::operator!= (TYPE *nptr) const
478{
479  return ( (TYPE*)ptr != nptr );
480}
481
482template <class TYPE> inline int
483GP<TYPE>::operator! () const
484{
485  return !ptr;
486}
487
488/* GPBUFFER */
489
490/* What is this LT innovation ?
491   What does it do that a GArray does not do ?
492   What about the objects construction and destruction ? */
493
494class DJVUAPI GPBufferBase
495{
496public:
497  GPBufferBase(void *&,const size_t n,const size_t t);
498  void swap(GPBufferBase &p);
499  void resize(const size_t n,const size_t t);
500  void replace(void *nptr,const size_t n);
501  void set(const size_t t,const char c);
502  ~GPBufferBase();
503  operator int(void) const { return ptr ? num : 0; }
504private:
505  void *&ptr;
506  size_t num;
507};
508
509template<class TYPE>
510class GPBuffer : public GPBufferBase
511{
512public:
513  GPBuffer(TYPE *&xptr,const size_t n=0) : GPBufferBase((void *&)xptr,n,sizeof(TYPE)) {}
514  inline void resize(const size_t n) {GPBufferBase::resize(n,sizeof(TYPE));}
515  inline void clear(void) {GPBufferBase::set(sizeof(TYPE),0);}
516  inline void set(const char c) {GPBufferBase::set(sizeof(TYPE),c);}
517  inline operator int(void) const {return GPBufferBase::operator int();}
518};
519
520
521
522#ifdef HAVE_NAMESPACES
523}
524# ifndef NOT_USING_DJVU_NAMESPACE
525using namespace DJVU;
526# endif
527#endif
528#endif
Note: See TracBrowser for help on using the repository browser.