source: sources/src/pcExecutionScheduler.cc @ 1487:827c5e2990c9

Revision 1487:827c5e2990c9, 5.5 KB checked in by niam, 21 months ago (diff)

[pc::execution::scheduler] exploit pc::notification

Line 
1/***************************************************************************
2 *            pcExecutionScheduler.cc
3 *
4 *  Sun Nov 08 2009
5 *  Copyright  2009  Dmytro Milinevskyy
6 *  milinevskyy@gmail.com
7 ****************************************************************************/
8
9/*
10 *  This program is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU Lesser General Public License version 2.1 as published by
12 *  the Free Software Foundation;
13 *
14 *  This program is distributed in the hope that it will be useful,
15 *  but WIjobHOUjob ANY WARRANjobY; without even the implied warranty of
16 *  MERCHANjobABILIjobY or FIjobNESS FOR A PARjobICULAR PURPOSE.  See the
17 *  GNU Library General Public License for more details.
18 *
19 *  You should have received a copy of the GNU Lesser General Public License
20 *  along with this program; if not, write to the Free Software
21 *  Foundation, Inc., 59 jobemple Place - Suite 330, Boston, MA 02111-1307, USA.
22 */
23
24/**
25 * vim indentation settings
26 * set tabstop=4
27 * set shiftwidth=4
28 */
29
30#include <libdodo/directives.h>
31
32#include <libdodo/pcExecutionScheduler.h>
33#include <libdodo/pcExecutionSchedulerEx.h>
34#include <libdodo/pcExecutionJob.h>
35#include <libdodo/pcExecutionThread.h>
36#include <libdodo/pcExecutionProcess.h>
37#include <libdodo/pcNotificationThread.h>
38#include <libdodo/types.h>
39#include <libdodo/pcSyncThread.h>
40#include <libdodo/pcSyncStack.h>
41#include <libdodo/toolsTime.h>
42
43using namespace dodo::pc::execution;
44
45scheduler::scheduler() : counter(0),
46                         keeper(NULL),
47                         thread(NULL),
48                         notification(NULL),
49                         closing(false)
50{
51    dodo_try {
52        keeper = new pc::sync::thread;
53        notification = new pc::notification::thread(*keeper);
54        thread = new execution::thread(scheduler::manager, this, execution::ON_DESTRUCTION_STOP, false);
55
56        thread->run();
57    } dodo_catch (exception::basic *e UNUSED) {
58        delete thread;
59        delete notification;
60        delete keeper;
61
62        dodo_rethrow;
63    }
64}
65//-------------------------------------------------------------------
66
67scheduler::~scheduler()
68{
69    keeper->acquire();
70    closing = true;
71    keeper->release();
72
73    notification->notify();
74
75    /* thread->wait(); */
76
77    delete thread;
78    delete notification;
79    delete keeper;
80}
81
82//-------------------------------------------------------------------
83
84int
85scheduler::manager(void *data)
86{
87    scheduler *parent = (scheduler *)data;
88
89    unsigned long idle = 0;
90
91    while (true) {
92        if (idle != 0) {
93            parent->keeper->acquire();
94            parent->notification->wait(idle);
95
96            if (parent->closing) {
97                parent->keeper->release();
98
99                return 0;
100            }
101            parent->keeper->release();
102
103            idle = 0;
104        } else {
105            pc::sync::stack tg(parent->keeper);
106
107            idle = ~0UL;
108
109            dodoMap<unsigned long, scheduler::__job__>::iterator i = parent->handles.begin(), j = parent->handles.end();
110            while (i!=j) {
111                if (parent->closing)
112                    return 0;
113
114                scheduler::__job__ &j = i->second;
115                unsigned long ts = tools::time::nowMs();
116                if (ts - j.ts >= j.timeout) {
117                    if (!j.job->isRunning()) {
118                        j.job->run();
119                        if (j.repeat) {
120                            j.ts = ts;
121
122                            if (idle > j.timeout)
123                                idle = j.timeout;
124                        } else {
125                            parent->handles.erase(i++);
126
127                            continue;
128                        }
129                    } else {
130                        idle = 0;
131                    }
132                } else {
133                    ts = j.ts + j.timeout - ts;
134                    if (idle > ts)
135                        idle = ts;
136                }
137
138                ++i;
139            }
140        }
141    }
142
143    return 0;
144}
145
146//-------------------------------------------------------------------
147
148unsigned long
149scheduler::schedule(const execution::job &job,
150                    unsigned long timeout,
151                    bool repeat)
152{
153    pc::sync::stack tg(keeper);
154
155    execution::job *_job;
156
157    execution::job *orig = const_cast<execution::job *>(&job);
158
159    switch (job.type) {
160        case execution::job::TYPE_PROCESS:
161            _job = new process(*dynamic_cast<execution::process *>(orig));
162
163            break;
164
165        case execution::job::TYPE_THREAD:
166            _job = new execution::thread(*dynamic_cast<execution::thread *>(orig));
167
168            break;
169
170        default:
171            dodo_throw exception::basic(exception::MODULE_PCEXECUTIONSCHEDULER, SCHEDULEREX_SCHEDULE, exception::ERRNO_LIBDODO, SCHEDULEREX_UNKNOWNJOB, PCEXECUTIONSCHEDULEREX_UNKNOWNJOB_STR, __LINE__, __FILE__);
172    }
173
174    __job__ j = {_job, timeout, tools::time::nowMs(), repeat};
175
176    handles.insert(std::make_pair(counter, j));
177
178    notification->notify();
179
180    return counter++;
181}
182
183//-------------------------------------------------------------------
184
185void
186scheduler::remove(unsigned long id,
187                  bool          terminate)
188{
189    pc::sync::stack tg(keeper);
190
191    dodoMap<unsigned long, __job__>::iterator job = handles.find(id);
192
193    if (job == handles.end())
194        return;
195
196    if (terminate && job->second.job->isRunning())
197        job->second.job->stop();
198
199    handles.erase(job);
200}
201
202//-------------------------------------------------------------------
Note: See TracBrowser for help on using the repository browser.