summaryrefslogtreecommitdiff
path: root/klm/util/stream/multi_progress.hh
blob: 82e698a59c32cdcd839293332781eaf0e2232d17 (plain)
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
/* Progress bar suitable for chains of workers */
#ifndef UTIL_STREAM_MULTI_PROGRESS_H
#define UTIL_STREAM_MULTI_PROGRESS_H

#include <boost/thread/mutex.hpp>

#include <cstddef>

#include <stdint.h>

namespace util { namespace stream {

class WorkerProgress;

class MultiProgress {
  public:
    static const unsigned char kWidth = 100;

    MultiProgress();

    ~MultiProgress();

    // Turns on showing (requires SetTarget too).
    void Activate();

    void SetTarget(uint64_t complete);

    WorkerProgress Add();

    void Finished();

  private:
    friend class WorkerProgress;
    void Milestone(WorkerProgress &worker);

    bool active_;

    uint64_t complete_;

    boost::mutex mutex_;

    // \0 at the end.  
    char display_[kWidth + 1];

    std::size_t character_handout_;

    MultiProgress(const MultiProgress &);
    MultiProgress &operator=(const MultiProgress &);
};

class WorkerProgress {
  public:
    // Default contrutor must be initialized with operator= later.  
    WorkerProgress() : parent_(NULL) {}

    // Not threadsafe for the same worker by default.  
    WorkerProgress &operator++() {
      if (++current_ >= next_) {
        parent_->Milestone(*this);
      }
      return *this;
    }

    WorkerProgress &operator+=(uint64_t amount) {
      current_ += amount;
      if (current_ >= next_) {
        parent_->Milestone(*this);
      }
      return *this;
    }

  private:
    friend class MultiProgress;
    WorkerProgress(uint64_t next, MultiProgress &parent, char character) 
      : current_(0), next_(next), parent_(&parent), stone_(0), character_(character) {}

    uint64_t current_, next_;

    MultiProgress *parent_;

    // Previous milestone reached.  
    unsigned char stone_;

    // Character to display in bar.  
    char character_;
};

}} // namespaces

#endif // UTIL_STREAM_MULTI_PROGRESS_H