1 // ==========================================================================
2 // SeqAn - The Library for Sequence Analysis
3 // ==========================================================================
4 // Copyright (c) 2006-2018, Knut Reinert, FU Berlin
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright
11 // notice, this list of conditions and the following disclaimer.
12 // * Redistributions in binary form must reproduce the above copyright
13 // notice, this list of conditions and the following disclaimer in the
14 // documentation and/or other materials provided with the distribution.
15 // * Neither the name of Knut Reinert or the FU Berlin nor the names of
16 // its contributors may be used to endorse or promote products derived
17 // from this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL KNUT REINERT OR THE FU BERLIN BE LIABLE
23 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 // OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 // DAMAGE.
30 //
31 // ==========================================================================
32 // Author: Andreas Gogol-Döring <andreas.doering@mdc-berlin.de>
33 // TODO(holtgrew): Or is this by Dave?
34 // ==========================================================================
35 // Pointer-like data structure that helps with the management of volatile
36 // data, used in external string during swapping. See class documentation
37 // for more details
38 // ==========================================================================
39
40 #ifndef SEQAN_BASIC_BASIC_VOLATILE_PTR_H_
41 #define SEQAN_BASIC_BASIC_VOLATILE_PTR_H_
42
43 namespace seqan {
44
45 // ============================================================================
46 // Forwards
47 // ============================================================================
48
49 // ============================================================================
50 // Tags, Classes, Enums
51 // ============================================================================
52
53 // TODO(holtgrew): Is volatile pointer the correct name?
54 // TODO(holtgrew): Metafunctions etc. missing.
55
56 /*!
57 * @class VolatilePtr
58 * @headerfile <seqan/basic.h>
59 * @brief Helper data structure for handling volatile data.
60 *
61 * @signature template <typename T>
62 * class VolatilePtr;
63 *
64 * @tparam T The pointed-to type.
65 *
66 * Allows you to handle volatile data (used by ext. string during swapping).
67 *
68 * Imagine volatile pointers as nodes in an undirected graph. When you assign one to another then they are connected.
69 * All pointers in a connection component points to the same value. By calling nukeCopies you can destroy
70 * the component and set all pointers to <tt>NULL</tt>.
71 */
72
73 template < typename Type >
74 struct VolatilePtr
75 {
76 typedef VolatilePtr Self_;
77 typedef VolatilePtr* SelfPtr_;
78 typedef VolatilePtr& SelfRef_;
79
80 typedef Type& reference;
81 typedef const Type& const_reference;
82 typedef Type* pointer;
83
84 pointer ptr;
85 SelfPtr_ next; // prev == NULL means this is the master node
86 SelfPtr_ prev; // prev == NULL means this is the master node
87
VolatilePtrVolatilePtr88 VolatilePtr() { // volatile pinters behave like normal pointers
89 prev = this; // and are not initialized (ptr) per default
90 next = this;
91 }
92
VolatilePtrVolatilePtr93 VolatilePtr(const pointer _p) {
94 ptr = _p;
95 prev = this;
96 next = this;
97 }
98
VolatilePtrVolatilePtr99 VolatilePtr(const Self_& _vp) {
100 ptr = _vp.ptr;
101 prev = this;
102 next = this;
103 }
104
VolatilePtrVolatilePtr105 VolatilePtr(SelfRef_ _vp) {
106 ptr = _vp.ptr;
107 prev = this;
108 next = this;
109 if (ptr) hangOn(_vp);
110 }
111
~VolatilePtrVolatilePtr112 ~VolatilePtr() {
113 hangOff();
114 }
115
116 template <typename size_type>
117 inline reference operator[] (size_type offset) {
118 return ptr[offset];
119 }
120
121 template <typename size_type>
122 inline const_reference operator[] (size_type offset) const {
123 return ptr[offset];
124 }
125
126 inline Self_& operator=(Self_ const &Right_) {
127 hangOff();
128 ptr = Right_.ptr;
129 if (ptr) hangOn(const_cast<Self_&>(Right_));
130 return *this;
131 }
132
133 inline Self_& operator=(pointer const Right_) {
134 hangOff();
135 ptr = Right_;
136 return *this;
137 }
138
139 // TODO(holtgrew): Move to global function?
isLonelyVolatilePtr140 inline bool isLonely() {
141 return next == this;
142 }
143
144 // TODO(holtgrew): Move to global function?
nukeCopiesVolatilePtr145 inline void nukeCopies() {
146 SelfPtr_ p = next;
147 while (p != this) {
148 SelfPtr_ tmp = p->next;
149 p->ptr = NULL;
150 p->prev = p;
151 p->next = p;
152 p = tmp;
153 }
154 prev = this;
155 next = this;
156 }
157
158 // TODO(holtgrew): Move to global function?
159 inline bool operator== (const Self_ &I) const {
160 return ptr == I.ptr;
161 }
162
163 // TODO(holtgrew): Move to global function?
164 inline bool operator!= (const Self_ &I) const {
165 return ptr != I.ptr;
166 }
167
pointerVolatilePtr168 inline operator pointer () const {
169 return ptr;
170 }
171
172 private:
173
hangOnVolatilePtr174 inline void hangOn(SelfRef_ _prev) {
175 // hang on between _prev and _prev.next
176 prev = &_prev;
177 next = _prev.next;
178 _prev.next = this;
179 next->prev = this;
180 }
181
hangOffVolatilePtr182 inline void hangOff() {
183 next->prev = prev;
184 prev->next = next;
185 next = this;
186 prev = this;
187 }
188 };
189
190 // ============================================================================
191 // Metafunctions
192 // ============================================================================
193
194 // ============================================================================
195 // Functions
196 // ============================================================================
197
198 // ----------------------------------------------------------------------------
199 // Function nukeCopies()
200 // ----------------------------------------------------------------------------
201
202 /*!
203 * @fn VolatilePtr#nukeCopies
204 * @brief Reset all pointers connected to a given one.
205 *
206 * @signature void nukeCopies(ptr);
207 *
208 * @param[in] ptr One pointer of the connected component to reset.
209 */
210
211 // TODO(holtgrew): Remove this version?
212 template <typename TValue>
nukeCopies(TValue * &)213 inline void nukeCopies(TValue * &)
214 {
215 }
216
217 template <typename TValue>
nukeCopies(VolatilePtr<TValue> & ptr)218 inline void nukeCopies(VolatilePtr<TValue> & ptr)
219 {
220 ptr.nukeCopies();
221 }
222
223 } // namespace seqan
224
225 #endif // #ifndef SEQAN_BASIC_BASIC_VOLATILE_PTR_H_
226