9773fca2fc1755e46d4ab2192fcdc42b30b8476e
[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 {
29 }
30
31 TimeScheduler::~TimeScheduler()
32 {
33 }
34
35 void
36 TimeScheduler::update(float time)
37 {
38   while(!schedule.empty() && schedule.front().wakeup_time < time) {
39     HSQOBJECT thread_ref = schedule.front().thread_ref;
40
41     sq_pushobject(global_vm, thread_ref);
42     sq_getweakrefval(global_vm, -1);
43
44     HSQUIRRELVM scheduled_vm;
45     if(sq_gettype(global_vm, -1) == OT_THREAD &&
46        SQ_SUCCEEDED(sq_getthread(global_vm, -1, &scheduled_vm))) {
47       if(SQ_FAILED(sq_wakeupvm(scheduled_vm, SQFalse, SQFalse, SQTrue, SQFalse))) {
48         std::ostringstream msg;
49         msg << "Error waking VM: ";
50         sq_getlasterror(scheduled_vm);
51         if(sq_gettype(scheduled_vm, -1) != OT_STRING) {
52           msg << "(no info)";
53         } else {
54           const char* lasterr;
55           sq_getstring(scheduled_vm, -1, &lasterr);
56           msg << lasterr;
57         }
58         log_warning << msg.str() << std::endl;
59         sq_pop(scheduled_vm, 1);
60       }
61     }
62
63     sq_release(global_vm, &thread_ref);
64     sq_pop(global_vm, 2);
65
66     std::pop_heap(schedule.begin(), schedule.end());
67     schedule.pop_back();
68   }
69 }
70
71 void
72 TimeScheduler::schedule_thread(HSQUIRRELVM scheduled_vm, float time)
73 {
74   // create a weakref to the VM
75   SQObject vm_obj = vm_to_object(scheduled_vm);
76   sq_pushobject(global_vm, vm_obj);
77   sq_weakref(global_vm, -1);
78
79   ScheduleEntry entry;
80   if(SQ_FAILED(sq_getstackobj(global_vm, -1, & entry.thread_ref))) {
81     sq_pop(global_vm, 2);
82     throw SquirrelError(global_vm, "Couldn't get thread weakref from vm");
83   }
84   entry.wakeup_time = time;
85
86   sq_addref(global_vm, & entry.thread_ref);
87   sq_pop(global_vm, 2);
88
89   schedule.push_back(entry);
90   std::push_heap(schedule.begin(), schedule.end());
91 }
92
93 }
94
95 /* EOF */