Merged changes from branches/supertux-milestone2-grumbel/ to trunk/supertux/
[supertux.git] / src / scripting / thread_queue.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 "scripting/thread_queue.hpp"
18
19 #include "scripting/squirrel_util.hpp"
20 #include "util/log.hpp"
21
22 namespace Scripting
23 {
24
25 ThreadQueue::ThreadQueue()
26 {
27 }
28
29 ThreadQueue::~ThreadQueue()
30 {
31 }
32
33 void
34 ThreadQueue::add(HSQUIRRELVM vm)
35 {
36   // create a weakref to the VM
37   HSQOBJECT vm_obj = vm_to_object(vm);
38   sq_pushobject(global_vm, vm_obj);
39   sq_weakref(global_vm, -1);
40
41   HSQOBJECT object;
42   if(SQ_FAILED(sq_getstackobj(global_vm, -1, &object))) {
43     sq_pop(global_vm, 2);
44     throw SquirrelError(global_vm, "Couldn't get thread weakref from vm");
45   }
46   sq_addref(global_vm, &object);
47   threads.push_back(object);
48
49   sq_pop(global_vm, 2);
50 }
51
52 void
53 ThreadQueue::wakeup()
54 {
55   // we traverse the list in reverse orders and use indices. This should be
56   // robust for scripts that add new entries to the list while we're traversing
57   // it
58   size_t i = threads.size() - 1;
59   size_t end = (size_t) 0 - 1;
60   size_t size_begin = threads.size();
61   while(i != end) {
62     HSQOBJECT object = threads[i];
63
64     sq_pushobject(global_vm, object);
65     sq_getweakrefval(global_vm, -1);
66
67     HSQUIRRELVM scheduled_vm;
68     if(sq_gettype(global_vm, -1) == OT_THREAD &&
69        SQ_SUCCEEDED(sq_getthread(global_vm, -1, &scheduled_vm))) {
70       if(SQ_FAILED(sq_wakeupvm(scheduled_vm, SQFalse, SQFalse, SQTrue, SQFalse))) {
71         log_warning << "Couldn't wakeup scheduled squirrel VM" << std::endl;
72       }
73     }
74
75     sq_release(global_vm, &object);
76     sq_pop(global_vm, 1);
77     i--;
78   }
79
80   threads.erase(threads.begin(), threads.begin() + size_begin);
81 }
82
83 }
84
85 /* EOF */