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