2
* Here is where the extensions can get timed on when they load and
3
* unload. All of the timing is done in here.
6
* Ted Gould <ted@gould.cx>
8
* Copyright (C) 2004 Authors
10
* Released under GNU GPL, read the file 'COPYING' for more information
15
#include "extension.h"
21
#define TIMER_SCALE_VALUE 20
23
ExpirationTimer * ExpirationTimer::timer_list = NULL;
24
ExpirationTimer * ExpirationTimer::idle_start = NULL;
25
long ExpirationTimer::timeout = 240;
26
bool ExpirationTimer::timer_started = false;
28
/** \brief Create a new expiration timer
29
\param in_extension Which extension this timer is related to
31
This function creates the timer, and sets the time to the current
32
time, plus what ever the current timeout is. Also, if this is
33
the first timer extension, the timer is kicked off. This function
34
also sets up teh circularly linked list of all the timers.
36
ExpirationTimer::ExpirationTimer (Extension * in_extension)
39
extension = in_extension;
42
if (timer_list == NULL) {
46
next = timer_list->next;
47
timer_list->next = this;
50
expiration.assign_current_time();
51
expiration += timeout;
54
Glib::signal_timeout().connect(sigc::ptr_fun(&timer_func), timeout * 1000 / TIMER_SCALE_VALUE);
61
/** \brief Deletes a \c ExpirationTimer
63
The most complex thing that this function does is remove the timer
64
from the circularly linked list. If this is the only entry in the
65
list that is easy, otherwise all the entries must be found, and this
66
one removed from the list.
68
ExpirationTimer::~ExpirationTimer(void)
71
/* This will remove this entry from the circularly linked
73
ExpirationTimer * prev;
74
for (prev = timer_list;
79
if (idle_start == this)
82
/* This may occur more than you think, just because the guy
83
doing most of the deletions is the idle function, who tracks
84
where it is looking using the \c timer_list variable. */
85
if (timer_list == this)
88
/* If we're the only entry in the list, the list needs to go
97
/** \brief Touches the timer to extend the length before it expires
99
Basically it adds more time to the timer. One thing that is kinda
100
tricky is that it adds half the time remaining back into the timer.
101
This allows for some extensions that are used regularly to having
102
extended expiration times. So, in the end, they stay loaded longer.
103
Extensions that are only used once will expire at a standard rate
107
ExpirationTimer::touch (void)
109
Glib::TimeVal current;
110
current.assign_current_time();
112
long time_left = (long)(expiration.as_double() - current.as_double());
113
if (time_left < 0) time_left = 0;
116
expiration = current + timeout + time_left;
120
/** \brief Check to see if the timer has expired
122
Checks the time against the current time.
125
ExpirationTimer::expired (void) const
127
if (locked) return false;
129
Glib::TimeVal current;
130
current.assign_current_time();
131
return expiration < current;
136
/** \brief This function goes in the idle loop to find expired extensions
137
\return Whether the function should be requeued or not
139
This function first insures that there is a timer list, and then checks
140
to see if the one on the top of the list has expired. If it has
141
expired it unloads the module. By unloading the module, the timer
142
gets deleted (happens in the unload function). If the list is
143
no empty, the function returns that it should be dequeued and sets
144
the \c timer_started variable so that the timer will be reissued when
145
a timer is added. If there is entries left, but the next one is
146
where this function started, then the timer is set up. The timer
147
will then re-add the idle loop function when it runs.
150
ExpirationTimer::idle_func (void)
152
// std::cout << "Idle func pass: " << idle_cnt++ << " timer list: " << timer_list << std::endl;
154
/* see if this is the last */
155
if (timer_list == NULL) {
156
timer_started = false;
160
/* evalutate current */
161
if (timer_list->expired()) {
162
timer_list->extension->set_state(Extension::STATE_UNLOADED);
165
/* see if this is the last */
166
if (timer_list == NULL) {
167
timer_started = false;
171
if (timer_list->next == idle_start) {
172
/* if so, set up the timer and return FALSE */
173
/* Note: This may cause one to be missed on the evaluation if
174
the one before it expires and it is last in the list.
175
While this could be taken care of, it isn't worth the
176
complexity for this lazy removal that we're doing. It
177
should get picked up next time */
178
Glib::signal_timeout().connect(sigc::ptr_fun(&timer_func), timeout * 1000 / TIMER_SCALE_VALUE);
182
/* If nothing else, continue on */
183
timer_list = timer_list->next;
187
/** \brief A timer function to set up the idle function
188
\return Always false -- to disable the timer
190
This function sets up the idle loop when it runs. The idle loop is
191
the one that unloads all the extensions.
194
ExpirationTimer::timer_func (void)
196
// std::cout << "Timer func" << std::endl;
197
idle_start = timer_list;
199
Glib::signal_idle().connect(sigc::ptr_fun(&idle_func));
203
}; }; /* namespace Inkscape, Extension */
208
c-file-style:"stroustrup"
209
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
214
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :