source: tags/svn.1.5.4/CORE/arb_progress.cxx

Last change on this file was 7623, checked in by westram, 13 years ago
  • merge from dev [7450] [7452] [7456] [7457] [7458] [7459] [7460] [7461] [7464] [7465] [7466] [7467] [7468] [7469] [7482]
    • tweaked compiler options
      • activated -Weffc++
        • postfilter warnings where Scott Meyers' advices are too general.
          • base classes should not always have virtual destructors, since that renders tiny classes useless and
          • members should not always be initialized via initialization list, since that often violates the DRY principle
        • fix gcc's inability to detect that Noncopyable implements a private copy-ctor and op=
        • this slows down complete ARB recompilation by ~5%
    • added -Wold-style-cast (inactive)
    • removed -Wno-non-template-friend added in [7447]
  • postcompile.pl
    • added option —original to show unmodified compiler output
  • declared op= for classes which had a copy-ctor
  • moved op= macros to arbtools.h
  • derived classes containing pointers from Noncopyable (use Noncopyable virtually) or
  • made them copyable if needed (awt_mask_item, KnownDB, Code, AWT_registered_itemtype, GEN_gene, PosGene, PartialSequence, PlugIn, Range, Convaln_exception)
  • other related changes
    • user mask destruction working now
File size: 9.4 KB
Line 
1// ================================================================ //
2//                                                                  //
3//   File      : arb_progress.cxx                                   //
4//   Purpose   :                                                    //
5//                                                                  //
6//   Coded by Ralf Westram (coder@reallysoft.de) in November 2010   //
7//   Institute of Microbiology (Technical University Munich)        //
8//   http://www.arb-home.de/                                        //
9//                                                                  //
10// ================================================================ //
11
12#include <arb_progress.h>
13#include <arb_handlers.h>
14#include <arb_msg.h>
15#include <algorithm>
16
17// ----------------
18//      counter
19
20struct null_counter: public arb_progress_counter {
21    null_counter(arb_parent_progress *progress_) : arb_progress_counter(progress_) {}
22
23    void inc() {}
24    void implicit_inc() {}
25    void done() {}
26    void restart(int) {}
27    void force_update() {}
28    void auto_subtitles(const char *) {}
29    bool has_auto_subtitles() { return false; }
30    void child_updates_gauge(double ) {
31        arb_assert(0); // wont
32    }
33
34#if defined(DUMP_PROGRESS)
35    void dump() {
36        fprintf(stderr, "null_counter\n");
37    }
38#endif
39
40    arb_progress_counter* clone(arb_parent_progress *parent_, int ) const { return new null_counter(parent_); }
41};
42
43struct no_counter : public null_counter {
44    no_counter(arb_parent_progress *progress_) : null_counter(progress_) {}
45    void inc() {
46        arb_assert(0); // this is no_counter - so explicit inc() is prohibited!
47    }
48    void child_updates_gauge(double gauge) { progress->update_gauge(gauge); }
49   
50#if defined(DUMP_PROGRESS)
51    void dump() {
52        fprintf(stderr, "no_counter (=wrapper)\n");
53    }
54#endif
55};
56
57class concrete_counter: public arb_progress_counter { // derived from a Noncopyable
58    int     explicit_counter; // incremented by calls to inc() etc.
59    int     implicit_counter; // incremented by child_done()
60    int     maxcount;         // == 0 -> does not really count (just a wrapper for child progresses)
61    double  autoUpdateEvery;
62    double  nextAutoUpdate;
63    char   *auto_subtitle_prefix;
64    int     last_auto_counter;
65
66    int dispositive_counter() const { return std::max(implicit_counter, explicit_counter); }
67
68    void init(int overallCount) {
69        arb_assert(overallCount>0);
70
71        implicit_counter  = 0;
72        explicit_counter  = 0;
73        maxcount          = overallCount;
74        autoUpdateEvery   = overallCount/500.0; // update status approx. 500 times
75        nextAutoUpdate    = 0;
76    }
77
78    bool refresh_if_needed(double my_counter) {
79        if (my_counter<nextAutoUpdate) return false;
80        progress->update_gauge(my_counter/maxcount);
81        if (auto_subtitle_prefix) {
82            int count = int(my_counter+1);
83            if (count>last_auto_counter) {
84                const char *autosub = GBS_global_string("%s #%i/%i", auto_subtitle_prefix, count, maxcount);
85                progress->set_text(LEVEL_SUBTITLE, autosub);
86                last_auto_counter   = count;
87            }
88        }
89        nextAutoUpdate += autoUpdateEvery;
90        return true;
91    }
92    void update_display_if_needed() {
93        int dcount = dispositive_counter();
94        arb_assert(dcount <= maxcount);
95        refresh_if_needed(dcount);
96    }
97
98    void force_update() {
99        int oldNext    = nextAutoUpdate;;
100        nextAutoUpdate = 0;
101        update_display_if_needed();
102        nextAutoUpdate = oldNext;
103    }
104
105public:
106    concrete_counter(arb_parent_progress *parent, int overall_count)
107        : arb_progress_counter(parent),
108          auto_subtitle_prefix(NULL),
109          last_auto_counter(0)
110    {
111        arb_assert(overall_count>0);
112        init(overall_count);
113    }
114    ~concrete_counter() {
115        free(auto_subtitle_prefix);
116#if defined(TEST_COUNTERS)
117        if (!progress->accept_invalid_counters) {
118            arb_assert(implicit_counter || explicit_counter); // progress was never incremented
119           
120            arb_assert(implicit_counter <= maxcount); // overflow
121            arb_assert(explicit_counter <= maxcount); // overflow
122
123            arb_assert(dispositive_counter() == maxcount); // progress did not finish
124        }
125#endif
126    }
127
128#if defined(DUMP_PROGRESS)
129    void dump() {
130        fprintf(stderr,
131                "concrete_counter: explicit=%i, implicit=%i, maxcount=%i\n", 
132                explicit_counter, implicit_counter, maxcount);
133    }
134#endif
135
136    void auto_subtitles(const char *prefix) {
137        arb_assert(!auto_subtitle_prefix);
138        freedup(auto_subtitle_prefix, prefix);
139        force_update();
140    }
141    bool has_auto_subtitles() { return auto_subtitle_prefix; }
142
143    void inc()          { explicit_counter += 1; update_display_if_needed(); }
144    void implicit_inc() { implicit_counter += 1; update_display_if_needed(); }
145   
146    void done() {
147        implicit_counter = explicit_counter = maxcount;
148        force_update();
149    }
150
151    void restart(int overallCount) {
152        init(overallCount);
153        force_update();
154    }
155
156    arb_progress_counter* clone(arb_parent_progress *parent, int overall_count) const{
157        return new concrete_counter(parent, overall_count);
158    }
159    void child_updates_gauge(double child_gauge) {
160        refresh_if_needed(dispositive_counter()+child_gauge);
161    }
162};
163
164// -----------------
165//      progress
166
167
168class child_progress : public arb_parent_progress { // derived from a Noncopyable
169    arb_parent_progress *parent;
170
171public:
172    child_progress(arb_parent_progress *parent_, const char *title, int overall_count)
173        : arb_parent_progress(overall_count
174                              ? (arb_progress_counter*)new concrete_counter(this, overall_count)
175                              : (arb_progress_counter*)new no_counter(this),
176                              title),
177          parent(parent_)
178    {
179        set_text(LEVEL_TITLE, title);
180#if defined(DUMP_PROGRESS)
181        freedup(name, GBS_global_string("child: %s", title));
182#endif
183    }
184    ~child_progress() {
185        parent->child_terminated();
186    }
187
188    SmartPtr<arb_parent_progress> create_child_progress(const char *title, int overall_count) {
189        return new child_progress(this, title, overall_count);
190    }
191
192#if defined(DUMP_PROGRESS)
193    void dump() {
194        arb_parent_progress::dump();
195        fprintf(stderr, "is child of\n");
196        parent->dump();
197    }
198#endif
199
200    bool aborted() const { return parent->aborted(); }
201    void set_text(int level, const char *text) { parent->child_sets_text(level+has_title-1, text); }
202   
203    void update_gauge(double gauge) { parent->child_updates_gauge(gauge); }
204};
205
206class initial_progress: public arb_parent_progress {
207    bool user_abort;
208   
209public:
210    initial_progress(const char *title, arb_progress_counter *counter_)
211        : arb_parent_progress(counter_, title),
212          user_abort(false)
213    {
214        arb_assert(title); // initial progress should have a title
215        impl->openstatus(title);
216#if defined(DUMP_PROGRESS)
217        freedup(name, GBS_global_string("initial: %s", title));
218#endif
219    }
220    ~initial_progress() {
221        update_gauge(1.0); // due to numeric issues it often only counts up to 99.999%
222        impl->closestatus();
223    }
224
225    SmartPtr<arb_parent_progress> create_child_progress(const char *title, int overall_count) {
226        return new child_progress(this, title, overall_count);
227    }
228
229    bool aborted() const { return user_abort; }
230    void set_text(int level, const char *text) {
231        if (!text) return;
232        switch (level+has_title-1) {
233            case LEVEL_TITLE: impl->set_title(text); break;
234            case LEVEL_SUBTITLE: impl->set_subtitle(text); break;
235        }
236    }
237
238    void update_gauge(double gauge) { user_abort = impl->set_gauge(gauge); }
239};
240
241struct initial_wrapping_progress: public initial_progress {
242    initial_wrapping_progress(const char *title)
243        : initial_progress(title, new no_counter(this)) {}
244};
245struct initial_counting_progress : public initial_progress {
246    initial_counting_progress(const char *title, int overall_count)
247        : initial_progress(title, new concrete_counter(this, overall_count)) {}
248};
249
250class null_progress: public arb_parent_progress {
251public:
252    null_progress(arb_progress_counter *counter_)
253        : arb_parent_progress(counter_, false)
254    {
255#if defined(DUMP_PROGRESS)
256        freedup(name, "null_progress");
257#endif
258    }
259
260    SmartPtr<arb_parent_progress> create_child_progress(const char*, int overall_count) {
261        return new null_progress(clone_counter(overall_count));
262    }
263    bool aborted() const { return false; }
264    void set_text(int,const char*) {}
265    void update_gauge(double) {}
266};
267
268// -------------------------
269//      progress factory
270
271arb_parent_progress       *arb_parent_progress::recent = NULL;
272arb_status_implementation *arb_parent_progress::impl   = NULL; // defines implementation to display status
273
274SmartPtr<arb_parent_progress> arb_parent_progress::create(const char *title, int overall_count) {
275    if (recent) {
276        return recent->create_child_progress(title, overall_count);
277    }
278
279    impl = &active_arb_handlers->status;
280
281    if (overall_count == 0) return new initial_wrapping_progress(title);
282    return new initial_counting_progress(title, overall_count);
283
284}
285
286SmartPtr<arb_parent_progress> arb_parent_progress::create_suppressor() {
287    return new null_progress(new null_counter(NULL));
288}
289
Note: See TracBrowser for help on using the repository browser.