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