source: tags/ms_r18q1/PARSIMONY/AP_buffer.hxx

Last change on this file was 17110, checked in by westram, 6 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : AP_buffer.hxx                                     //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#ifndef AP_BUFFER_HXX
12#define AP_BUFFER_HXX
13
14#ifndef AP_SEQUENCE_HXX
15#include <AP_sequence.hxx>
16#endif
17#ifndef ARB_FORWARD_LIST_H
18#include <arb_forward_list.h>
19#endif
20#ifndef _GLIBCXX_SET
21#include <set>
22#endif
23
24/* AP_STACK        Stack container
25 *
26 * -- buffers
27 *
28 * NodeState  holds (partial) state of AP_tree_nlen
29 *
30 * -- used stacks
31 *
32 * StateStack      stack containing NodeState* (each AP_tree_nlen contains one)
33 * NodeStack       stack containing AP_tree_nlen* (NodeStack of current frame is member of AP_main)
34 * FrameStack      stack containing NodeStacks (member of AP_main, stores previous NodeStack frames)
35 */
36
37template <typename ELEM>
38struct AP_STACK : public arb_forward_list<ELEM*> {
39    typedef arb_forward_list<ELEM*>       BASE;
40    typedef typename BASE::iterator       iterator;
41    typedef typename BASE::const_iterator const_iterator;
42
43    void push(ELEM *element) {
44        //! add 'element' to top of stack
45        BASE::push_front(element);
46    }
47    void shift(ELEM *element) {
48        //! add 'element' to bottom of stack
49#if defined(Cxx11)
50        // uses forward_list
51        if (BASE::empty()) {
52            push(element);
53        }
54        else {
55            iterator i = BASE::begin();
56            iterator n = i;
57            while (true) {
58                if (++n == BASE::end()) {
59                    BASE::insert_after(i, element);
60                    break;
61                }
62                i = n;
63            }
64        }
65#else
66        // uses list
67        BASE::push_back(element);
68#endif
69    }
70    ELEM *pop() {
71        if (BASE::empty()) return NULp;
72
73        ELEM *result = top();
74        BASE::pop_front();
75        return result;
76    }
77
78    ELEM *top() {
79        ap_assert(!BASE::empty());
80        return BASE::front();
81    }
82    const ELEM *top() const {
83        ap_assert(!BASE::empty());
84        return BASE::front();
85    }
86
87    size_t count_elements() const {
88#if defined(Cxx11)
89        size_t s = 0;
90        for (const_iterator i = BASE::begin(); i != BASE::end(); ++i) ++s;
91        return s;
92#else // !defined(Cxx11)
93        return BASE::size();
94#endif
95    }
96
97    bool empty() const { return BASE::empty(); }
98};
99
100// ----------------------------------------------------------------
101//      special buffer-structures for AP_tree and AP_tree_edge
102
103#if defined(DEBUG)
104#define PROVIDE_PRINT
105#endif
106
107#if defined(PROVIDE_PRINT)
108#include <ostream>
109#endif
110
111
112class AP_tree_edge; // defined in ap_tree_nlen.hxx
113
114enum AP_STACK_MODE {
115    NOTHING   = 0, // nothing to buffer in AP_tree node
116    STRUCTURE = 1, // only structure
117    SEQUENCE  = 2, // only sequence
118    BOTH      = 3, // sequence & treestructure is buffered
119    ROOT      = 7  // old root is buffered (includes BOTH)
120};
121
122class AP_tree_nlen;
123class AP_pars_root;
124
125typedef unsigned long Level;
126
127struct NodeState : virtual Noncopyable { // buffers previous states of AP_tree_nlen
128    Level         frameNr;  // state of AP_tree_nlen::remembered_for_frame at creation time of NodeState
129    AP_STACK_MODE mode;     // what has been stored?
130
131    // only defined if mode & SEQUENCE:
132    AP_sequence *sequence;  // if set -> NodeState is owner!
133    Mutations    mutations;
134
135    // only defined if mode & STRUCTURE:
136    double        leftlen, rightlen;
137    AP_tree_nlen *father;
138    AP_tree_nlen *leftson;
139    AP_tree_nlen *rightson;
140    AP_pars_root *root;
141    GBDATA       *gb_node;
142    int           keelState;
143    AP_tree_edge *edge[3];
144    int           edgeIndex[3];
145
146    // defined/restored if mode & (SEQUENCE|STRUCTURE):
147    unsigned mark_sum;
148
149    void move_info_to(NodeState& target, AP_STACK_MODE what);
150
151#if defined(PROVIDE_PRINT)
152    void print(std::ostream& out, int indentLevel = 0) const;
153#endif
154
155    explicit NodeState(Level frame_nr) : frameNr(frame_nr), mode(NOTHING), mutations(0) {}
156    ~NodeState() { if (mode & SEQUENCE) delete sequence; }
157};
158
159struct StateStack : public AP_STACK<NodeState> {
160#if defined(PROVIDE_PRINT)
161    void print(std::ostream& out, int indentLevel = 0) const;
162#endif
163};
164
165class AP_tree_nlen;
166class AP_tree_edge;
167
168#if defined(ASSERTION_USED)
169#define CHECK_ROOT_POPS
170#endif
171
172typedef std::set<AP_tree_nlen*> NodeSet;
173typedef std::set<AP_tree_edge*> EdgeSet;
174
175class ResourceStack {
176    // stores nodes and edges for resource management
177    NodeSet nodes;
178    EdgeSet edges;
179public:
180    ResourceStack() {}
181    ~ResourceStack() {
182        ap_assert(nodes.empty());
183        ap_assert(edges.empty());
184    }
185
186    void extract_common(ResourceStack& stack1, ResourceStack& stack2);
187
188    void destroy_nodes();
189    void destroy_edges();
190    void forget_nodes();
191    void forget_edges();
192    void move_nodes(ResourceStack& target);
193    void move_edges(ResourceStack& target);
194
195    AP_tree_nlen *put(AP_tree_nlen *node) { nodes.insert(node); return node; }
196    AP_tree_edge *put(AP_tree_edge *edge) { edges.insert(edge); return edge; }
197
198    AP_tree_nlen *getNode() { ap_assert(!nodes.empty()); AP_tree_nlen *result = *nodes.begin(); nodes.erase(nodes.begin()); return result; }
199    AP_tree_edge *getEdge() { ap_assert(!edges.empty()); AP_tree_edge *result = *edges.begin(); edges.erase(edges.begin()); return result; }
200
201    bool has_nodes() const { return !nodes.empty(); }
202    bool has_edges() const { return !edges.empty(); }
203
204    bool has_node(AP_tree_nlen *node) const { return nodes.find(node) != nodes.end(); }
205};
206
207class StackFrameData : virtual Noncopyable {
208    // data local to current stack frame
209    // as well exists for stack frame = 0 (i.e. when nothing has been remember()ed yet)
210
211    ResourceStack created;   // nodes and edges created in the current stack frame
212    ResourceStack destroyed; // same for destroyed
213
214public:
215    bool  root_pushed; // @@@ move into NodeStack
216    StackFrameData() : root_pushed(false) {}
217
218    void revert_resources(StackFrameData *previous);
219    void accept_resources(StackFrameData *previous, ResourceStack *common);
220
221    void extract_common_to(ResourceStack& common) { common.extract_common(created, destroyed); }
222
223    inline AP_tree_nlen *makeNode(AP_pars_root *proot);
224    inline AP_tree_edge *makeEdge(AP_tree_nlen *n1, AP_tree_nlen *n2);
225    inline void destroyNode(AP_tree_nlen *node);
226    inline void destroyEdge(AP_tree_edge *edge);
227};
228
229#if defined(ASSERTION_USED)
230#define CHECK_STACK_RESOURCE_HANDLING
231#endif
232
233class NodeStack : public AP_STACK<AP_tree_nlen> { // derived from Noncopyable
234    StackFrameData *previous;
235#if defined(CHECK_STACK_RESOURCE_HANDLING)
236    enum ResHandled { NO, ACCEPTED, REVERTED } resources_handled;
237#endif
238
239public:
240    explicit NodeStack(StackFrameData*& data)
241        : previous(data)
242#if defined(CHECK_STACK_RESOURCE_HANDLING)
243        , resources_handled(NO)
244#endif
245    {
246        data = NULp; // take ownership
247    }
248    ~NodeStack() {
249        ap_assert(!previous); // forgot to use take_previous_frame_data()
250#if defined(CHECK_STACK_RESOURCE_HANDLING)
251        ap_assert(resources_handled != NO);
252#endif
253    }
254
255    StackFrameData *take_previous_frame_data() {
256        StackFrameData *release = previous;
257        previous = NULp;     // release ownership
258        return release;
259    }
260
261    void revert_resources(StackFrameData *current) {
262#if defined(CHECK_STACK_RESOURCE_HANDLING)
263        ap_assert(resources_handled == NO);
264        resources_handled = REVERTED;
265#endif
266        current->revert_resources(previous);
267    }
268    void accept_resources(StackFrameData *current, ResourceStack *common) {
269#if defined(CHECK_STACK_RESOURCE_HANDLING)
270        ap_assert(resources_handled == NO);
271        resources_handled = ACCEPTED;
272#endif
273        current->accept_resources(previous, common);
274    }
275
276#if defined(CHECK_ROOT_POPS)
277    AP_tree_nlen *root_at_create; // root at creation time of stack
278#endif
279#if defined(PROVIDE_PRINT)
280    void print(std::ostream& out, int indentLevel, Level frameNr) const;
281#endif
282};
283
284struct FrameStack : public AP_STACK<NodeStack> {
285#if defined(PROVIDE_PRINT)
286    void print(std::ostream& out, int indentLevel = 0) const;
287#endif
288};
289
290#else
291#error AP_buffer.hxx included twice
292#endif // AP_BUFFER_HXX
Note: See TracBrowser for help on using the repository browser.