squirrel_scheduler.cpp 2.9 KB

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