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 "squirrel/squirrel_scheduler.hpp"
18
19#include <algorithm>
20
21#include "squirrel/squirrel_virtual_machine.hpp"
22#include "squirrel/squirrel_util.hpp"
23#include "util/log.hpp"
24
25SquirrelScheduler::SquirrelScheduler(SquirrelVM& vm) :
26 m_vm(vm),
27 schedule()
28{
29}
30
31void
32SquirrelScheduler::update(float time)
33{
34 while (!schedule.empty() && schedule.front().wakeup_time < time) {
35 HSQOBJECT thread_ref = schedule.front().thread_ref;
36
37 sq_pushobject(m_vm.get_vm(), thread_ref);
38 sq_getweakrefval(m_vm.get_vm(), -1);
39
40 HSQUIRRELVM scheduled_vm;
41 if (sq_gettype(m_vm.get_vm(), -1) == OT_THREAD &&
42 SQ_SUCCEEDED(sq_getthread(m_vm.get_vm(), -1, &scheduled_vm))) {
43 if (SQ_FAILED(sq_wakeupvm(scheduled_vm, SQFalse, SQFalse, SQTrue, SQFalse))) {
44 std::ostringstream msg;
45 msg << "Error waking VM: ";
46 sq_getlasterror(scheduled_vm);
47 if (sq_gettype(scheduled_vm, -1) != OT_STRING) {
48 msg << "(no info)";
49 } else {
50 const char* lasterr;
51 sq_getstring(scheduled_vm, -1, &lasterr);
52 msg << lasterr;
53 }
54 log_warning << msg.str() << std::endl;
55 sq_pop(scheduled_vm, 1);
56 }
57 }
58
59 sq_release(m_vm.get_vm(), &thread_ref);
60 sq_pop(m_vm.get_vm(), 2);
61
62 std::pop_heap(schedule.begin(), schedule.end());
63 schedule.pop_back();
64 }
65}
66
67void
68SquirrelScheduler::schedule_thread(HSQUIRRELVM scheduled_vm, float time)
69{
70 // create a weakref to the VM
71 sq_pushthread(m_vm.get_vm(), scheduled_vm);
72 sq_weakref(m_vm.get_vm(), -1);
73
74 ScheduleEntry entry;
75 if (SQ_FAILED(sq_getstackobj(m_vm.get_vm(), -1, & entry.thread_ref))) {
76 sq_pop(m_vm.get_vm(), 2);
77 throw SquirrelError(m_vm.get_vm(), "Couldn't get thread weakref from vm");
78 }
79 entry.wakeup_time = time;
80
81 sq_addref(m_vm.get_vm(), & entry.thread_ref);
82 sq_pop(m_vm.get_vm(), 2);
83
84 schedule.push_back(entry);
85 std::push_heap(schedule.begin(), schedule.end());
86}
87
88/* EOF */
89