File: arb_progress.h

package info (click to toggle)
arb 6.0.2-1%2Bdeb8u1
  • links: PTS, VCS
  • area: non-free
  • in suites: jessie
  • size: 65,916 kB
  • ctags: 53,258
  • sloc: ansic: 394,903; cpp: 250,252; makefile: 19,620; sh: 15,878; perl: 10,461; fortran: 6,019; ruby: 683; xml: 503; python: 53; awk: 32
file content (270 lines) | stat: -rw-r--r-- 9,034 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
// ================================================================ //
//                                                                  //
//   File      : arb_progress.h                                     //
//   Purpose   :                                                    //
//                                                                  //
//   Coded by Ralf Westram (coder@reallysoft.de) in November 2010   //
//   Institute of Microbiology (Technical University Munich)        //
//   http://www.arb-home.de/                                        //
//                                                                  //
// ================================================================ //

#ifndef ARB_PROGRESS_H
#define ARB_PROGRESS_H

#ifndef ARB_ASSERT_H
#include <arb_assert.h>
#endif
#ifndef ARB_ERROR_H
#include <arb_error.h>
#endif
#ifndef ARBTOOLS_H
#include <arbtools.h>
#endif

#if defined(DEBUG)
#if defined(DEVEL_RALF)
#define DUMP_PROGRESS
#define TEST_COUNTERS
#endif
#endif


class  arb_parent_progress;
struct arb_status_implementation;

class arb_progress_counter : virtual Noncopyable {
protected:
    arb_parent_progress *progress;
public:
    arb_progress_counter(arb_parent_progress *progress_)
        : progress(progress_)
    {}
    virtual ~arb_progress_counter() {}

    virtual void inc()                              = 0;
    virtual void implicit_inc()                     = 0;
    virtual void inc_to(int x)                      = 0;
    virtual void child_updates_gauge(double gauge)  = 0;
    virtual void done()                             = 0;
    virtual void force_update()                     = 0;
    virtual void restart(int overall_count)         = 0;
    virtual void auto_subtitles(const char *prefix) = 0;
    virtual bool has_auto_subtitles()               = 0;

#if defined(DUMP_PROGRESS)
    virtual void dump() = 0;
#endif

    virtual arb_progress_counter *clone(arb_parent_progress *parent, int overall_count) const = 0;
};

const int LEVEL_TITLE    = 0;
const int LEVEL_SUBTITLE = 1;

class arb_parent_progress : virtual Noncopyable {
    arb_parent_progress *prev_recent;
    bool                 reuse_allowed; // display may be reused by childs

protected:
#if defined(DUMP_PROGRESS)
    char *name;
#endif
    
    bool                  has_title;
    arb_progress_counter *counter;

    static arb_parent_progress       *recent;
    static arb_status_implementation *impl; // defines implementation to display status

    virtual SmartPtr<arb_parent_progress> create_child_progress(const char *title, int overall_count) = 0;

    arb_parent_progress(arb_progress_counter *counter_, bool has_title_) 
        : reuse_allowed(false),
          has_title(has_title_),
          counter(counter_)
    {
        prev_recent = recent;
        recent      = this;
        
#if defined(DUMP_PROGRESS)
        name = NULL;
#endif

#if defined(TEST_COUNTERS)
        accept_invalid_counters = false;
#endif
    }
public:
#if defined(TEST_COUNTERS)
    bool accept_invalid_counters; // if true, do not complain about unfinished counters
#endif

    virtual ~arb_parent_progress() {
        delete counter;
        recent = prev_recent;
#if defined(DUMP_PROGRESS)
        free(name);
#endif
    }

    static SmartPtr<arb_parent_progress> create(const char *title, int overall_count);
    static SmartPtr<arb_parent_progress> create_suppressor();

    virtual bool aborted() const                       = 0;
    virtual void set_text(int level, const char *text) = 0;
    virtual void update_gauge(double gauge)            = 0;

#if defined(DUMP_PROGRESS)
    virtual void dump();
#endif

    void child_sets_text(int level, const char *text) {
        set_text(level+1-reuse_allowed+counter->has_auto_subtitles(), text);
    }
    void allow_title_reuse() { reuse_allowed = true; }

    void child_updates_gauge(double gauge) { counter->child_updates_gauge(gauge); }
    void child_terminated() { counter->implicit_inc(); }

    arb_progress_counter *clone_counter(int overall_count) { return counter->clone(this, overall_count); }
    void initial_update() { counter->force_update(); }
    void force_update() { counter->force_update(); }

    void inc() { counter->inc(); }
    void inc_to(int x) { counter->inc_to(x); }
    void done() { counter->done(); }
    void auto_subtitles(const char *prefix) { counter->auto_subtitles(prefix); }

    static void show_comment(const char *comment) {
        if (recent) recent->set_text(LEVEL_SUBTITLE, comment);
    }
};

class arb_progress {
    SmartPtr<arb_parent_progress> used;

    void setup(const char *title, int overall_count) {
        used = arb_parent_progress::create(title, overall_count);
        used->initial_update();
    }
    // cppcheck-suppress functionConst
    void accept_invalid_counters() {
#if defined(TEST_COUNTERS)
        used->accept_invalid_counters = true;
#endif
    }

public:
    // ------------------------------
    // recommended interface:

    arb_progress(const char *title, int overall_count) {
        // open a progress indicator
        // 
        // expects to be incremented 'overall_count' times
        //      incrementation is done either
        //      - explicitly by calling one of the inc...()-functions below or
        //      - implicitely by creating another arb_progress while this one remains
        //
        // if you can't ahead-determine the exact number of incrementations,
        // specify an upper-limit and call .done() before dtor.

        arb_assert(overall_count >= 0);
        setup(title, overall_count);
    }
    explicit arb_progress(const char *title) {
        // open a wrapping progress indicator
        //
        // expects NOT to be incremented explicitly!
        //      if arb_progresses are created while this exists, they reuse the progress window.
        //      Useful to avoid spamming the user with numerous popping-up progress windows.
        setup(title, 0);
    }
    explicit arb_progress(int overall_count) {
        // open counting progress (reuses text of parent progress).
        // 
        // Useful to separate text- from gauge-display or
        // to summarize several consecutive child-progresses into one.
        setup(NULL, overall_count);
    }
    arb_progress() {
        // plain wrapper (avoids multiple implicit increments of its parent).
        // 
        // usage-conditions:
        // * caller increments progress in a loop and
        // * loop calls one or more callees and callees open multiple progress bars.
        // 
        // in this case the parent progress would be implicitely incremented several times
        // per loop, resulting in wrong gauge.
        //
        // if you know the number of opened progresses, use arb_progress(int),
        // otherwise add one wrapper-progress into the loop.
        setup(NULL, 0);
    }

    void allow_title_reuse() { used->allow_title_reuse(); }

    void subtitle(const char *stitle) { used->set_text(LEVEL_SUBTITLE, stitle); }

    GB_ERROR error_if_aborted() {
        return aborted() ? "Operation aborted on user request" : NULL;
    }

    GB_ERROR inc_and_error_if_aborted() {
        inc();
        return error_if_aborted();
    }

    void inc_and_check_user_abort(GB_ERROR& error)  { if (!error) error = inc_and_error_if_aborted(); else accept_invalid_counters(); }
    void inc_and_check_user_abort(ARB_ERROR& error) { if (!error) error = inc_and_error_if_aborted(); else accept_invalid_counters(); }

    bool aborted() {
        // true if user pressed "Abort"
        bool aborted_ = used->aborted();
#if defined(TEST_COUNTERS)
        if (aborted_) accept_invalid_counters();
#endif
        return aborted_;
    }

    void auto_subtitles(const char *prefix) {
        // automatically update subtitles ("prefix #/#")
        // prefix = NULL -> switch off
        used->auto_subtitles(prefix);
    }
    static void show_comment(const char *comment) {
        // Like subtitle(), but w/o needing to know anything about a eventually open progress
        // e.g. used to show ARB is connecting to ptserver
        arb_parent_progress::show_comment(comment);
    }
    
    // ------------------------------
    // less recommended interface:

    void inc() { used->inc(); } // increment progress
    const arb_progress& operator++() { inc(); return *this; } // ++progress

    void inc_by(int count) { arb_assert(count>0); while (count--) inc(); }
    void inc_to(int x) { used->inc_to(x); }

    void sub_progress_skipped() { used->child_terminated(); }

    void done() { used->done(); } // set "done" (aka 100%). Useful when exiting some loop early
#if defined(DUMP_PROGRESS)
    void dump();
#endif
    void force_update() { used->force_update(); }
};

class arb_suppress_progress {
    SmartPtr<arb_parent_progress> suppressor;
public:
    arb_suppress_progress()
        : suppressor(arb_parent_progress::create_suppressor())
    {}
};

#else
#error arb_progress.h included twice
#endif // ARB_PROGRESS_H