Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 423 lines (272 sloc) 9.43 kB
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
1 /*
2 Copyright (C) 2001-2007, The Perl Foundation.
3 $Id$
4
5 =head1 NAME
6
7 src/pmc/scheduler.pmc - The concurrency scheduler
8
9 =head1 DESCRIPTION
10
11 Implements the core concurrency scheduler.
12
d6808fe @allisonrandal [events] Add interface for event handling, add subtype attribute to t…
allisonrandal authored
13 =head2 Vtable Functions
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
14
15 =over 4
16
17 =cut
18
19 */
20
21 #include "parrot/parrot.h"
ec73fb3 @allisonrandal [concurrency] Divide scheduler headers into public and private (for c…
allisonrandal authored
22 #include "parrot/scheduler_private.h"
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
23
24 pmclass Scheduler need_ext {
25
26 /*
27
28 =item C<void init()>
29
30 Initialize a concurrency scheduler object.
31
32 =cut
33
34 */
35
36 void init() {
728a876 @petdance consting, and removed two unused vars
petdance authored
37 Parrot_Scheduler * const core_struct = mem_allocate_zeroed_typed(Parrot_Scheduler);
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
38
39 /* Set flags for custom DOD mark and destroy. */
40 PObj_custom_mark_SET(SELF);
41 PObj_active_destroy_SET(SELF);
42
43 /* Set up the core struct. */
44 PMC_data(SELF) = core_struct;
45 core_struct->id = 0;
46 core_struct->max_tid = 0;
47 core_struct->task_list = pmc_new(interp, enum_class_Hash);
245b0a8 @allisonrandal [concurrency] Change an array of task IDs to an integer array rather …
allisonrandal authored
48 core_struct->task_index = pmc_new(interp, enum_class_ResizableIntegerArray);
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
49 core_struct->handlers = pmc_new(interp, enum_class_ResizablePMCArray);
2f43c23 @allisonrandal [concurrency] Initialize interp struct member in Scheduler. Add a way to
allisonrandal authored
50 core_struct->interp = INTERP;
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
51
52 }
53
54 /*
55
96858ee @chromatic [PMC] Added init_pmc() to Scheduler PMC, with tests.
chromatic authored
56 =item C<void init_pmc(PMC *data)>
57
58 Initializes a new Scheduler with a C<Hash> PMC with any or all of the keys:
59
60 =over 4
61
62 =item C<id>
63
64 An C<Integer> representing the unique identifier for this scheduler.
65
66 =back
67
68 */
69
70 void init_pmc(PMC *data) {
71 PMC *elem;
72 Parrot_Scheduler *core_struct;
73
74 if (! VTABLE_isa(INTERP, data, CONST_STRING(INTERP, "Hash")))
75 real_exception(INTERP, NULL, INVALID_OPERATION,
76 "Task initializer must be a Hash");
77
78 core_struct = mem_allocate_zeroed_typed(Parrot_Scheduler);
79
80 /* Set flags for custom DOD mark and destroy. */
81 PObj_custom_mark_SET(SELF);
82 PObj_active_destroy_SET(SELF);
83
84 /* Set up the core struct. */
85 PMC_data(SELF) = core_struct;
86
87 elem = VTABLE_get_pmc_keyed_str(INTERP, data, CONST_STRING(INTERP, "id"));
88
89 if (! PMC_IS_NULL(elem))
90 core_struct->id = VTABLE_get_integer(INTERP, elem);
91 else
92 core_struct->id = 0;
93
94 core_struct->max_tid = 0;
95 core_struct->task_list = pmc_new(interp, enum_class_Hash);
245b0a8 @allisonrandal [concurrency] Change an array of task IDs to an integer array rather …
allisonrandal authored
96 core_struct->task_index = pmc_new(interp, enum_class_ResizableIntegerArray);
96858ee @chromatic [PMC] Added init_pmc() to Scheduler PMC, with tests.
chromatic authored
97 core_struct->handlers = pmc_new(interp, enum_class_ResizablePMCArray);
98 core_struct->interp = INTERP;
99 }
100
101 /*
102
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
103 =item C<void push_pmc(PMC *value)>
104
105 Insert a task into the task list, giving it a task ID one higher than the
106 current maximum.
107
108 =cut
109
110 */
111
e922116 @allisonrandal [concurrency] Initial implementation of concurrency scheduler runloop.
allisonrandal authored
112 void push_pmc(PMC *task) {
728a876 @petdance consting, and removed two unused vars
petdance authored
113 Parrot_Scheduler * const core_struct = PARROT_SCHEDULER(SELF);
245b0a8 @allisonrandal [concurrency] Change an array of task IDs to an integer array rather …
allisonrandal authored
114 STRING *task_id_str;
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
115
d0fb13e @allisonrandal [concurrency] Tasks are marked as shared before being inserted into t…
allisonrandal authored
116 task = pt_shared_fixup(INTERP, task);
117
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
118 core_struct->max_tid++;
e922116 @allisonrandal [concurrency] Initial implementation of concurrency scheduler runloop.
allisonrandal authored
119 VTABLE_set_integer_native(INTERP, task, core_struct->max_tid);
245b0a8 @allisonrandal [concurrency] Change an array of task IDs to an integer array rather …
allisonrandal authored
120 task_id_str = string_from_int(INTERP, core_struct->max_tid);
121
df0a91e @allisonrandal [concurrency] Resolving synchronization problem, new event must not s…
allisonrandal authored
122 LOCK(core_struct->lock);
123 VTABLE_set_pmc_keyed_str(INTERP, core_struct->task_list, task_id_str, task);
245b0a8 @allisonrandal [concurrency] Change an array of task IDs to an integer array rather …
allisonrandal authored
124 VTABLE_push_integer(INTERP, core_struct->task_index, core_struct->max_tid);
e922116 @allisonrandal [concurrency] Initial implementation of concurrency scheduler runloop.
allisonrandal authored
125 Parrot_cx_runloop_wake(core_struct->interp, SELF);
df0a91e @allisonrandal [concurrency] Resolving synchronization problem, new event must not s…
allisonrandal authored
126 UNLOCK(core_struct->lock);
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
127 }
128
129 /*
130
131 =item C<PMC *pop_pmc()>
132
133 Retrieve the next task from the task list. If the task index is invalid,
134 recalculate it before retrieving the next task.
135
136 =cut
137
138 */
139
140 PMC *pop_pmc() {
141 Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
142
143 /* if (!SCHEDULER_cache_valid_TEST(SELF))
144 Parrot_task_recalculate_index(INTERP, SELF); */
145
146 if (VTABLE_elements(INTERP, core_struct->task_index) > 0) {
d0fb13e @allisonrandal [concurrency] Tasks are marked as shared before being inserted into t…
allisonrandal authored
147 INTVAL tid = VTABLE_shift_integer(INTERP, core_struct->task_index);
245b0a8 @allisonrandal [concurrency] Change an array of task IDs to an integer array rather …
allisonrandal authored
148 return VTABLE_get_pmc_keyed_int(INTERP, core_struct->task_list, tid);
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
149 }
150 else
151 return PMCNULL;
152
153 }
154
155 /*
156
2f43c23 @allisonrandal [concurrency] Initialize interp struct member in Scheduler. Add a way to
allisonrandal authored
157 =item C<INTVAL get_integer()>
158
159 Retrieve the number of pending tasks in the scheduler's task list.
160
161 =cut
162
163 */
164
165 INTVAL get_integer() {
166 Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
167 return VTABLE_elements(INTERP, core_struct->task_index);
168 }
169
d6808fe @allisonrandal [events] Add interface for event handling, add subtype attribute to t…
allisonrandal authored
170
2f43c23 @allisonrandal [concurrency] Initialize interp struct member in Scheduler. Add a way to
allisonrandal authored
171 /*
172
173 =item C<void delete_keyed_int(INTVAL key)>
174
175 Removes the task with the given task ID from the task list.
176
177 =cut
178
179 */
180
181 void delete_keyed_int(INTVAL key) {
182 Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
183 PMC * const pmc_key = pmc_new(INTERP, enum_class_Integer);
184 VTABLE_set_integer_native(INTERP, pmc_key, key);
185 VTABLE_delete_keyed(INTERP, core_struct->task_list, pmc_key);
186 SCHEDULER_cache_valid_CLEAR(SELF);
187 }
188
189 /*
190
e922116 @allisonrandal [concurrency] Initial implementation of concurrency scheduler runloop.
allisonrandal authored
191 =item C<PMC *share_ro()>
192
193 Set this PMC as shared.
194
195 =cut
196
197 */
198
199 PMC *share_ro() {
200 PMC *shared_self;
201 Parrot_Scheduler *shared_struct;
202
203 if (PObj_is_PMC_shared_TEST(SELF))
204 return SELF;
205
206 shared_self = pt_shared_fixup(INTERP, SELF);
207 shared_struct = PARROT_SCHEDULER(shared_self);
208
209 shared_struct->task_list = pt_shared_fixup(INTERP, shared_struct->task_list);
210 shared_struct->task_index = pt_shared_fixup(INTERP, shared_struct->task_index);
211 shared_struct->handlers = pt_shared_fixup(INTERP, shared_struct->handlers);
212
213 return shared_self;
214 }
215
216 /*
217
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
218 =item C<void destroy()>
219
220 Free the scheduler's underlying struct.
221
222 =cut
223
224 */
225 void destroy() {
e922116 @allisonrandal [concurrency] Initial implementation of concurrency scheduler runloop.
allisonrandal authored
226 Parrot_Scheduler * const core_struct = PARROT_SCHEDULER(SELF);
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
227 mem_sys_free(PMC_data(SELF));
228 }
229
230 /*
231
232 =item C<void mark()>
233
234 Mark any referenced strings and PMCs.
235
236 =cut
237
238 */
239 void mark() {
240 if (PARROT_SCHEDULER(SELF)) {
241 Parrot_Scheduler * const core_struct = PARROT_SCHEDULER(SELF);
242
243 if (core_struct->task_list)
244 pobject_lives(interp, (PObj*)core_struct->task_list);
245 if (core_struct->task_index)
246 pobject_lives(interp, (PObj*)core_struct->task_index);
247 if (core_struct->handlers)
248 pobject_lives(interp, (PObj*)core_struct->handlers);
249 }
250 }
251
252 /*
253
254 =item C<void visit(visit_info *info)>
255
256 This is used by freeze/thaw to visit the contents of the scheduler.
257
258 C<*info> is the visit info, (see F<include/parrot/pmc_freeze.h>).
259
260 =cut
261
262 */
263
264 void visit(visit_info *info) {
728a876 @petdance consting, and removed two unused vars
petdance authored
265 Parrot_Scheduler * const core_struct = PARROT_SCHEDULER(SELF);
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
266 PMC **pos;
267
268 /* 1) visit task list */
269 pos = &core_struct->task_list;
270 info->thaw_ptr = pos;
271 (info->visit_pmc_now)(INTERP, *pos, info);
272
273 /* 2) visit the handlers */
274 pos = &core_struct->handlers;
275 info->thaw_ptr = pos;
276 (info->visit_pmc_now)(INTERP, *pos, info);
277 }
278
279 /*
280
281 =item C<void freeze(visit_info *info)>
282
283 Used to archive the scheduler.
284
285 =cut
286
287 */
288
289 void freeze(visit_info *info) {
290 IMAGE_IO *io = info->image_io;
291 Parrot_Scheduler * const core_struct = PARROT_SCHEDULER(SELF);
292
293 /* 1) freeze scheduler id */
294 VTABLE_push_integer(INTERP, io, core_struct->id);
295
296 /* 2) freeze maximum task id */
297 VTABLE_push_integer(INTERP, io, core_struct->max_tid);
298 }
299
300 /*
301
302 =item C<void thaw(visit_info *info)>
303
304 Used to unarchive the scheduler.
305
306 =cut
307
308 */
309
310 void thaw(visit_info *info) {
728a876 @petdance consting, and removed two unused vars
petdance authored
311 IMAGE_IO * const io = info->image_io;
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
312
313 /* 1. thaw scheduler id */
728a876 @petdance consting, and removed two unused vars
petdance authored
314 const INTVAL id = VTABLE_shift_integer(INTERP, io);
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
315
316 /* 2. thaw maximum task id */
728a876 @petdance consting, and removed two unused vars
petdance authored
317 const INTVAL max_tid = VTABLE_shift_integer(INTERP, io);
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
318
319 /* Allocate the scheduler's core data struct and set custom flags. */
320 SELF.init();
321
322 /* Set the scheduler's id to the frozen id */
323 PARROT_SCHEDULER(SELF)->id = id;
324
325 /* Set the scheduler's maximum task id to the frozen tid */
326 PARROT_SCHEDULER(SELF)->max_tid = max_tid;
327 }
328
329 /*
330
331 =item C<void thawfinish(visit_info *info)>
332
333 Called after the scheduler has been thawed.
334
335 =cut
336
337 */
338
339 void thawfinish(visit_info *info) {
728a876 @petdance consting, and removed two unused vars
petdance authored
340 Parrot_Scheduler * const core_struct = PARROT_SCHEDULER(SELF);
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
341
342 /* TODO: Rebuild the task index. */
343 }
344
d6808fe @allisonrandal [events] Add interface for event handling, add subtype attribute to t…
allisonrandal authored
345 /*
346
347 =back
348
349 =head2 Methods
350
351 =over 4
352
353 =cut
354
355 */
356
357 /*
358
359 =item C<PCCMETHOD add_handler(PMC *handler)>
360
361 Add a handler to the scheduler.
362
363 =cut
364
365 */
366
367 PCCMETHOD add_handler(PMC *handler) {
368 Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
369 VTABLE_push_pmc(INTERP, core_struct->handlers, handler);
370 }
371 /*
372
373 =item C<PCCMETHOD find_handler(PMC *task)>
374
375 Search for a handler for the given task. If no handler is found, return
376 PMCNULL.
377
378 =cut
379
380 */
381
382 PCCMETHOD find_handler(PMC *task) {
383 Parrot_Scheduler * core_struct = PARROT_SCHEDULER(SELF);
384 INTVAL elements = VTABLE_elements(INTERP, core_struct->handlers);
385 INTVAL counter;
386
387 for (counter = 0; counter < elements; ++counter) {
388 PMC *handler = VTABLE_get_pmc_keyed_int(interp,
389 core_struct->handlers, counter);
390 INTVAL valid_handler = 0;
391 if (!PMC_IS_NULL(handler)) {
392 (INTVAL valid_handler) = PCCINVOKE(interp, handler, "can_handle", PMC *task);
393 if (valid_handler) {
394 PCCRETURN(PMC *handler);
395 }
396 }
397 }
398
399 PCCRETURN(PMC *PMCNULL);
400
401 }
402
1d259c6 @allisonrandal [concurrency] Initial implementations of the Scheduler and Task PMCs.
allisonrandal authored
403 }
404
405 /*
406
407 =back
408
409 =head1 SEE ALSO
410
411 F<docs/pdds/pdd15_objects.pod>.
412
413 =cut
414
415 */
416
417 /*
418 * Local variables:
419 * c-file-style: "parrot"
420 * End:
421 * vim: expandtab shiftwidth=4:
422 */
Something went wrong with that request. Please try again.