OSDN Git Service

tests: skip failing use of mkfs.hfs unless using newer, fixed version
[android-x86/external-parted.git] / libparted / timer.c
1 /*
2     libparted - a library for manipulating disk partitions
3     Copyright (C) 2001, 2007, 2009-2012 Free Software Foundation, Inc.
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 3 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 /** \file timer.c */
20
21 /**
22  * \addtogroup PedTimer
23  *
24  * \brief A PedTimer keeps track of the progress of a single (possibly
25  * compound) operation.
26  *
27  * The user of libparted constructs a PedTimer, and passes it to libparted
28  * functions that are likely to be expensive operations
29  * (like ped_file_system_resize).  Use of timers is optional... you may
30  * pass NULL instead.
31  *
32  * When you create a PedTimer, you must specify a timer handler function.
33  * This will be called when there's an update on how work is progressing.
34  *
35  * Timers may be nested.  When a timer is constructed, you can choose
36  * to assign it a parent, along with an estimate of what proportion of
37  * the total (parent's) time will be used in the nested operation.  In
38  * this case, the nested timer's handler is internal to libparted,
39  * and simply updates the parent's progress, and calls its handler.
40  *
41  * @{
42  */
43
44
45 #include <config.h>
46 #include <parted/parted.h>
47 #include <parted/debug.h>
48
49 typedef struct {
50         PedTimer*       parent;
51         float           nest_frac;
52         float           start_frac;
53 } NestedContext;
54
55
56 /**
57  * \brief Creates a timer.
58  *
59  * Context will be passed in the \p context
60  *         argument to the \p handler, when it is invoked.
61  *
62  * \return a new PedTimer
63  */
64 PedTimer*
65 ped_timer_new (PedTimerHandler* handler, void* context)
66 {
67         PedTimer*       timer;
68
69         PED_ASSERT (handler != NULL);
70
71         timer = (PedTimer*) ped_malloc (sizeof (PedTimer));
72         if (!timer)
73                 return NULL;
74
75         timer->handler = handler;
76         timer->context = context;
77         ped_timer_reset (timer);
78         return timer;
79 }
80
81
82 /**
83  * \brief Destroys a \p timer.
84  */
85 void
86 ped_timer_destroy (PedTimer* timer)
87 {
88         if (!timer)
89                 return;
90
91         free (timer);
92 }
93
94 /* This function is used by ped_timer_new_nested() as the timer->handler
95  * function.
96  */
97 static void
98 _nest_handler (PedTimer* timer, void* context)
99 {
100         NestedContext*  ncontext = (NestedContext*) context;
101
102         ped_timer_update (
103                 ncontext->parent,
104                 ncontext->start_frac + ncontext->nest_frac * timer->frac);
105 }
106
107
108 /**
109  * \brief Creates a new nested timer.
110  *
111  * This function creates a "nested" timer that describes the progress
112  * of a subtask. \p parent is the parent timer, and \p nested_frac is
113  * the estimated proportion (between 0 and 1) of the time that will be
114  * spent doing the nested timer's operation. The timer should only be
115  * constructed immediately prior to starting the nested operation.
116  * (It will be inaccurate, otherwise).
117  * Updates to the progress of the subtask are propagated
118  * back through to the parent task's timer.
119  *
120  * \return nested timer
121  */
122 PedTimer*
123 ped_timer_new_nested (PedTimer* parent, float nest_frac)
124 {
125         NestedContext*  context;
126
127         if (!parent)
128                 return NULL;
129
130         PED_ASSERT (nest_frac >= 0.0f);
131         PED_ASSERT (nest_frac <= 1.0f);
132
133         context = (NestedContext*) ped_malloc (sizeof (NestedContext));
134         if (!context)
135                 return NULL;
136         context->parent = parent;
137         context->nest_frac = nest_frac;
138         context->start_frac = parent->frac;
139
140         return ped_timer_new (_nest_handler, context);
141 }
142
143 /**
144  * \brief Destroys a nested \p timer.
145  */
146 void
147 ped_timer_destroy_nested (PedTimer* timer)
148 {
149         if (!timer)
150                 return;
151
152         free (timer->context);
153         ped_timer_destroy (timer);
154 }
155
156 /**
157  * \internal
158  *
159  * \brief This function calls the update handler, making sure that it has
160  *      the latest time.
161  *
162  * First it updates \p timer->now and recomputes \p timer->predicted_end,
163  * and then calls the handler.
164  */
165 void
166 ped_timer_touch (PedTimer* timer)
167 {
168         if (!timer)
169                return;
170
171         timer->now = time (NULL);
172         if (timer->now > timer->predicted_end)
173                 timer->predicted_end = timer->now;
174
175         timer->handler (timer, timer->context);
176 }
177
178 /**
179  * \internal
180  *
181  * \brief This function sets the \p timer into a "start of task" position.
182  *
183  * It resets the \p timer, by setting \p timer->start and \p timer->now
184  * to the current time.
185  */
186 void
187 ped_timer_reset (PedTimer* timer)
188 {
189         if (!timer)
190                return;
191
192         timer->start = timer->now = timer->predicted_end = time (NULL);
193         timer->state_name = NULL;
194         timer->frac = 0;
195
196         ped_timer_touch (timer);
197 }
198
199 /**
200  * \internal
201  *
202  * \brief This function tells a \p timer what fraction \p frac of the task
203  * has been completed.
204  *
205  * Sets the new \p timer->frac, and calls ped_timer_touch().
206  */
207 void
208 ped_timer_update (PedTimer* timer, float frac)
209 {
210         if (!timer)
211                return;
212
213         timer->now = time (NULL);
214         timer->frac = frac;
215
216         if (frac)
217                 timer->predicted_end
218                         = timer->start
219                           + (long) ((timer->now - timer->start) / frac);
220
221         ped_timer_touch (timer);
222 }
223
224 /**
225  * \internal
226  *
227  * \brief This function changes the description of the current task that the
228  *      \p timer describes.
229  *
230  * Sets a new name - \p state_name - for the current "phase" of the operation,
231  * and calls ped_timer_touch().
232  */
233 void
234 ped_timer_set_state_name (PedTimer* timer, const char* state_name)
235 {
236         if (!timer)
237                return;
238
239         timer->state_name = state_name;
240         ped_timer_touch (timer);
241 }
242
243 /** @} */