degate  0.1.2
ProgressControl.h
Go to the documentation of this file.
00001 /* -*-c++-*-
00002 
00003  This file is part of the IC reverse engineering tool degate.
00004 
00005  Copyright 2008, 2009, 2010 by Martin Schobert
00006 
00007  Degate is free software: you can redistribute it and/or modify
00008  it under the terms of the GNU General Public License as published by
00009  the Free Software Foundation, either version 3 of the License, or
00010  any later version.
00011 
00012  Degate is distributed in the hope that it will be useful,
00013  but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  GNU General Public License for more details.
00016 
00017  You should have received a copy of the GNU General Public License
00018  along with degate. If not, see <http://www.gnu.org/licenses/>.
00019 
00020 */
00021 
00022 #ifndef __PROGRESSCONTROL_H__
00023 #define __PROGRESSCONTROL_H__
00024 
00025 #include <memory>
00026 #include <time.h>
00027 #include <boost/thread.hpp>
00028 
00029 namespace degate {
00030 
00031   /**
00032    */
00033 
00034   class ProgressControl {
00035 
00036   private:
00037 
00038     const static int averaging_buf_size = 5;
00039 
00040     double progress;
00041     bool canceled;
00042 
00043     double step_size;
00044     time_t time_started;
00045 
00046     time_t estimated[averaging_buf_size];
00047     int estimated_idx;
00048 
00049     std::string log_message;
00050     bool log_message_set;
00051 
00052     boost::recursive_mutex mtx;
00053 
00054   private:
00055 
00056     time_t get_time_left_averaged() {
00057       estimated[estimated_idx++] = get_time_left();
00058       estimated_idx %= averaging_buf_size;
00059 
00060       unsigned int sum = 0, valid_values = 0;
00061       for(int i = 0; i < averaging_buf_size; i++)
00062         if(estimated[i] != -1) {
00063           sum += estimated[i];
00064           valid_values++;
00065         }
00066 
00067       return valid_values > 0 ? sum / valid_values : get_time_left_averaged();
00068     }
00069 
00070   protected:
00071 
00072     /**
00073      * Set progress.
00074      */
00075     virtual void set_progress(double progress) {
00076       boost::recursive_mutex::scoped_lock(mtx);
00077       this->progress = progress;
00078     }
00079 
00080     /**
00081      * Set step size.
00082      */
00083     virtual void set_progress_step_size(double step_size) {
00084       boost::recursive_mutex::scoped_lock(mtx);
00085       this->step_size = step_size;
00086     }
00087 
00088     /**
00089      * Increase progress.
00090      */
00091     virtual void progress_step_done() {
00092       boost::recursive_mutex::scoped_lock(mtx);
00093       progress += step_size;
00094     }
00095 
00096     /**
00097      * Reset progress and cancel state.
00098      */
00099     virtual void reset_progress() {
00100       boost::recursive_mutex::scoped_lock(mtx);
00101       time_started = time(NULL);
00102       canceled = false;
00103       progress = 0;
00104 
00105       for(int i = 0; i < averaging_buf_size; i++) estimated[i] = -1;
00106 
00107       estimated_idx = 0;
00108     }
00109 
00110   public:
00111 
00112     /**
00113      * The constructor
00114      */
00115 
00116     ProgressControl() : log_message_set(false) {
00117       reset_progress();
00118     }
00119 
00120     /**
00121      * The destructor for a plugin.
00122      */
00123 
00124     virtual ~ProgressControl() {}
00125 
00126     /**
00127      * Check if the process is canceled.
00128      */
00129 
00130     virtual bool is_canceled() const {
00131       boost::recursive_mutex::scoped_lock(mtx);
00132       return canceled;
00133     }
00134 
00135     /**
00136      * Stop the processing.
00137      */
00138 
00139     virtual void cancel() {
00140       boost::recursive_mutex::scoped_lock(mtx);
00141       canceled = true;
00142     }
00143 
00144 
00145     /**
00146      * Get progress.
00147      * @return Returns a value between 0 and 100 percent.
00148      */
00149 
00150     virtual double get_progress() const {
00151       boost::recursive_mutex::scoped_lock(mtx);
00152       return progress;
00153     }
00154 
00155     /**
00156      * Get (real) time since the progress counter was resetted.
00157      */
00158     virtual time_t get_time_passed() const {
00159       boost::mutex::scoped_lock(m_mutex);
00160       return time(NULL) - time_started;
00161     }
00162 
00163     /**
00164      * Get estimated time left in seconds.
00165      * @return Returns the time to go in seconds or -1, if
00166      *   that time cannot be calculated.
00167      */
00168     virtual time_t get_time_left() const {
00169       boost::recursive_mutex::scoped_lock(mtx);
00170       if(progress < 1.0)
00171         return progress > 0 ? (1.0 - progress) * get_time_passed() / progress : -1;
00172       return 0;
00173     }
00174 
00175     virtual std::string get_time_left_as_string() {
00176       boost::recursive_mutex::scoped_lock(mtx);
00177       time_t time_left = get_time_left_averaged();
00178       if(time_left == -1) return std::string("-");
00179       else {
00180         char buf[100];
00181         if(time_left < 60)
00182           snprintf(buf, sizeof(buf), "%d s", (int)time_left);
00183         else if(time_left < 60*60)
00184           snprintf(buf, sizeof(buf), "%d:%02d m", (int)time_left / 60, (int)time_left % 60);
00185         else {
00186           unsigned int minutes = (int)time_left / 60;
00187           snprintf(buf, sizeof(buf), "%d:%02d h", minutes / 60, (int)time_left % 60);
00188         }
00189         return std::string(buf);
00190       }
00191 
00192     }
00193 
00194 
00195     virtual void set_log_message(std::string const& msg) {
00196       boost::recursive_mutex::scoped_lock(mtx);
00197       log_message = msg;
00198       log_message_set = true;
00199     }
00200 
00201     virtual std::string get_log_message() const {
00202       boost::recursive_mutex::scoped_lock(mtx);
00203       return log_message;
00204     }
00205 
00206     virtual bool has_log_message() const {
00207       boost::recursive_mutex::scoped_lock(mtx);
00208       return log_message_set;
00209     }
00210   };
00211 
00212   typedef std::shared_ptr<ProgressControl> ProgressControl_shptr;
00213 }
00214 
00215 #endif
00216