Fix for UBSan build
[platform/upstream/doxygen.git] / src / lockingptr.h
1 /******************************************************************************
2  *
3  * $Id: $
4  *
5  * Copyright (C) 1997-2012 by Dimitri van Heesch.
6  *
7  * Permission to use, copy, modify, and distribute this software and its
8  * documentation under the terms of the GNU General Public License is hereby 
9  * granted. No representations are made about the suitability of this software 
10  * for any purpose. It is provided "as is" without express or implied warranty.
11  * See the GNU General Public License for more details.
12  *
13  * Documents produced by Doxygen are derivative works derived from the
14  * input used in their production; they are not affected by this license.
15  *
16  */
17
18 #ifndef LOCKINGPTR_H
19 #define LOCKINGPTR_H
20
21 /*! @brief Abstract interface for lockable objects.
22  *
23  *  By implementing this interface, a smart pointer can be created which
24  *  will lock this object. This is used to prevent that an internal pointer
25  *  owned by a lockable object would become invalid when the object is removed from 
26  *  memory, leaving the client with an invalid pointer. By letting the client use 
27  *  a smart pointer instead of the real object the object will be locked into
28  *  memory until the pointer is no longer used, at which point the owner object will be
29  *  unlock and can be removed from memory.
30  */
31 class LockableObj
32 {
33   public:
34     LockableObj() : m_lockCount(0) {}
35     virtual ~LockableObj() {}
36
37     /*! Returns TRUE if the object is currently locked. */
38     bool isLocked() const { return m_lockCount>0; }
39
40 //VC++6.0 workaround
41 //  protected:
42     /*! Called when the object is locked. */
43     virtual void lock() const = 0;
44
45     /*! Called when the object is unlocked. */
46     virtual void unlock() const = 0;
47
48 //VC++6.0 workaround
49 //  private:
50 //    template<class T> friend class LockingPtr;
51     int  m_lockCount;
52 };
53
54 /*! @brief Smart pointer which keeps a lock on the owner of the pointer.
55  *
56  *  With the pointer an owner object derived from LockableObj is associated.
57  *  As long as the smart object exists it will keep a lock on the obj by calling 
58  *  LockableObj::lock(). Smart pointers can be copied and passed by value. As 
59  *  soon as there or no more smart pointer references to the object, 
60  *  LockableObj::unlock() will be called automatically.
61  */
62 template<class T> class LockingPtr
63 {
64     LockableObj *m_owner;
65     const T *m_ptr;
66
67   public:
68     /*! Creates a smart pointer for pointer \a p owned by object \a o.
69      */
70     LockingPtr(const LockableObj *o,const T* p) 
71     { 
72       if (o->m_lockCount==0) o->lock(); 
73       m_owner = (LockableObj *)o;
74       m_owner->m_lockCount++;
75       m_ptr = p;
76     }
77     
78     /*! Copies the smart pointer \a lp 
79      */
80     LockingPtr(const LockingPtr &lp)
81     {
82       m_ptr   = lp.m_ptr;
83       m_owner = lp.m_owner;
84       m_owner->m_lockCount++;
85     }
86
87     /*! Assigns the smart pointer \a lp 
88      */
89     LockingPtr &operator=(const LockingPtr &lp)
90     {
91       m_owner->m_lockCount--;
92       if (m_owner->m_lockCount==0) // no more references
93       {
94         m_owner->unlock(); 
95       }
96       m_ptr   = lp.m_ptr;
97       m_owner = lp.m_owner;
98       m_owner->m_lockCount++;
99       return *this;
100     }
101
102     /*! Destroys the smart pointer, will unlock the owner.
103      */
104     ~LockingPtr() 
105     { 
106       m_owner->m_lockCount--;
107       if (m_owner->m_lockCount==0) // no more references
108       {
109         m_owner->unlock(); 
110       }
111     }
112
113     bool isNull() const
114     {
115       return m_ptr==0;
116     }
117
118     bool operator!() const
119     {
120       return !m_ptr;
121     }
122
123     bool operator==(T *p) const
124     {
125       return m_ptr==p;
126     }
127
128     bool operator==(const LockingPtr &lp) const
129     {
130       return m_ptr==lp.m_ptr;
131     }
132
133     bool operator!=(T *p) const
134     {
135       return m_ptr!=p;
136     }
137
138     bool operator!=(const LockingPtr &lp) const
139     {
140       return m_ptr!=lp.m_ptr;
141     }
142
143     /*! Dereference operator */
144     const T& operator* () const
145     { 
146       return *m_ptr; 
147     }
148
149     T* pointer() const
150     {
151       return (T*)m_ptr;
152     }
153     
154     /*! Pointer operator */
155     T* operator-> () const
156     { 
157       return (T*)m_ptr; 
158     }
159 };
160
161 #endif // LOCKINGPTR_H
162