8c3314b74e22233aa0b0522979de68c675a73191
[supertux.git] / src / scripting / time_scheduler.cpp
1 //  $Id$
2 //
3 //  SuperTux
4 //  Copyright (C) 2006 Matthias Braun <matze@braunis.de>
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 //  02111-1307, USA.
20 #include <config.h>
21
22 #include <algorithm>
23
24 #include "time_scheduler.hpp"
25 #include "squirrel_util.hpp"
26 #include "squirrel_error.hpp"
27 #include "log.hpp"
28
29 namespace Scripting
30 {
31
32 TimeScheduler* TimeScheduler::instance = NULL;
33
34 TimeScheduler::TimeScheduler()
35 {
36 }
37
38 TimeScheduler::~TimeScheduler()
39 {
40 }
41
42 void
43 TimeScheduler::update(float time)
44 {
45   while(!schedule.empty() && schedule.front().wakeup_time < time) {
46     HSQOBJECT thread_ref = schedule.front().thread_ref;
47
48     sq_pushobject(global_vm, thread_ref);
49     sq_getweakrefval(global_vm, -1);
50
51     HSQUIRRELVM scheduled_vm;
52     if(sq_gettype(global_vm, -1) == OT_THREAD &&
53         SQ_SUCCEEDED(sq_getthread(global_vm, -1, &scheduled_vm))) {
54       if(SQ_FAILED(sq_wakeupvm(scheduled_vm, SQFalse, SQFalse, SQTrue))) {
55         std::ostringstream msg;
56         msg << "Couldn't wakeup scheduled squirrel VM: ";
57         sq_getlasterror(scheduled_vm);
58         if(sq_gettype(scheduled_vm, -1) != OT_STRING) {
59             msg << "(no info)";
60         } else {
61             const char* lasterr;
62             sq_getstring(scheduled_vm, -1, &lasterr);
63             msg << lasterr;
64         }
65         log_warning << msg.str() << std::endl;
66         sq_pop(scheduled_vm, 1);
67       }
68     }
69
70     sq_release(global_vm, &thread_ref);
71     sq_pop(global_vm, 2);
72
73     std::pop_heap(schedule.begin(), schedule.end());
74     schedule.pop_back();
75   }
76 }
77
78 void
79 TimeScheduler::schedule_thread(HSQUIRRELVM scheduled_vm, float time)
80 {
81   // create a weakref to the VM
82   SQObject vm_obj = vm_to_object(scheduled_vm);
83   sq_pushobject(global_vm, vm_obj);
84   sq_weakref(global_vm, -1);
85
86   ScheduleEntry entry;
87   if(SQ_FAILED(sq_getstackobj(global_vm, -1, & entry.thread_ref))) {
88     sq_pop(global_vm, 2);
89     throw SquirrelError(global_vm, "Couldn't get thread weakref from vm");
90   }
91   entry.wakeup_time = time;
92
93   sq_addref(global_vm, & entry.thread_ref);
94   sq_pop(global_vm, 2);
95
96   schedule.push_back(entry);
97   std::push_heap(schedule.begin(), schedule.end());
98 }
99
100 }
101