added "jammod" command and "genman" module
[k8jam.git] / src / progress.c
blobca24251be5ddd6c90b887b28405bc07aa776849b
1 /*
2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation, either version 3 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #include <stdlib.h>
16 #include <string.h>
17 #include <time.h>
19 #include "jam.h"
20 #include "lists.h"
21 #include "parse.h"
22 #include "rules.h"
23 #include "newstr.h"
24 #include "hash.h"
25 #include "variable.h"
26 #include "search.h"
28 #include "progress.h"
31 #define PROGRESS_WINDOW (10)
34 typedef struct {
35 time_t when;
36 int completed;
37 } TIMESTAMP;
40 struct _PROGRESS {
41 int total;
42 int stampcount;
43 TIMESTAMP stamps[PROGRESS_WINDOW];
47 static double get_time_delta (void) {
48 static double res = 10.0;
49 static int checked = 0;
50 if (!checked) {
51 LIST *var = var_get("K8JAM-PROGRESS-TIME-DELTA"); /*FIXME: a perfectly idiotic name*/
52 if (var) {
53 TARGET *t = bindtarget(var->string);
54 pushsettings(t->settings);
55 t->boundname = search(t->name, &t->time);
56 popsettings(t->settings);
57 if (t->boundname) {
58 res = atof(t->boundname);
59 if (res < 0.0) res = 0.0;
61 checked = 1;
64 return res;
68 #define LAST_STAMP(p) ((p)->stamps[(p)->stampcount-1])
69 #define FIRST_STAMP(p) ((p)->stamps[0])
72 PROGRESS *progress_start (int total) {
73 PROGRESS *p = malloc(sizeof(PROGRESS));
74 p->total = total;
75 p->stampcount = 0;
76 progress_update(p, 0);
77 return p;
81 static double progress_estimate (PROGRESS *progress) {
82 int count, left;
83 double elapsed, rate;
84 if (progress->stampcount < 2) return 0.0;
85 count = LAST_STAMP(progress).completed-FIRST_STAMP(progress).completed;
86 left = progress->total-LAST_STAMP(progress).completed;
87 elapsed = (double)(LAST_STAMP(progress).when-FIRST_STAMP(progress).when);
88 if (elapsed <= 0.1) elapsed = 0.1;
89 rate = count/elapsed;
90 return left/rate;
94 double progress_update (PROGRESS *progress, int completed) {
95 time_t now;
96 double dd = get_time_delta();
97 time(&now);
98 /* only return progress every 10 seconds */
99 if (progress->stampcount > 0 && (dd <= 0.00001 || difftime(now, LAST_STAMP(progress).when) < dd)) return 0.0;
100 if (progress->stampcount == PROGRESS_WINDOW) {
101 memmove(progress->stamps, progress->stamps+1, sizeof(progress->stamps[0])*(PROGRESS_WINDOW-1));
102 --progress->stampcount;
104 ++progress->stampcount;
105 LAST_STAMP(progress).completed = completed;
106 LAST_STAMP(progress).when = now;
107 return progress_estimate(progress);