source: branches/stable/PARSIMONY/AP_buffer.hxx

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