Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include "gui/auxiliary/timer.hpp"
00017
00018 #include "events.hpp"
00019 #include "gui/auxiliary/log.hpp"
00020
00021 #include <boost/static_assert.hpp>
00022
00023 #include <SDL_timer.h>
00024
00025 #include <map>
00026
00027 namespace gui2 {
00028
00029 struct ttimer
00030 {
00031 ttimer()
00032 : sdl_id(NULL)
00033 , interval(0)
00034 , callback()
00035 {
00036 }
00037
00038 SDL_TimerID sdl_id;
00039 Uint32 interval;
00040 boost::function<void(unsigned long id)> callback;
00041 };
00042
00043
00044 static unsigned long id = 0;
00045
00046
00047 static std::map<unsigned long, ttimer> timers;
00048
00049
00050 static unsigned long executing_id = 0;
00051
00052
00053 static bool executing_id_removed = false;
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 class texecutor
00069 {
00070 public:
00071 texecutor(unsigned long id)
00072 {
00073 executing_id = id;
00074 executing_id_removed = false;
00075
00076 }
00077
00078 ~texecutor()
00079 {
00080 const unsigned long id = executing_id;
00081 executing_id = 0;
00082 if(executing_id_removed) {
00083 remove_timer(id);
00084 }
00085 }
00086 };
00087
00088 extern "C" {
00089
00090 static Uint32 timer_callback(Uint32, void* id)
00091 {
00092 DBG_GUI_E << "Pushing timer event in queue.\n";
00093
00094 std::map<unsigned long, ttimer>::iterator itor =
00095 timers.find(reinterpret_cast<unsigned long>(id));
00096 if(itor == timers.end()) {
00097 return 0;
00098 }
00099
00100 SDL_Event event;
00101 SDL_UserEvent data;
00102
00103 data.type = TIMER_EVENT;
00104 data.code = 0;
00105 data.data1 = id;
00106 data.data2 = NULL;
00107
00108 event.type = TIMER_EVENT;
00109 event.user = data;
00110
00111 SDL_PushEvent(&event);
00112
00113 return itor->second.interval;
00114 }
00115
00116 }
00117
00118 unsigned long
00119 add_timer(const Uint32 interval
00120 , const boost::function<void(unsigned long id)>& callback
00121 , const bool repeat)
00122 {
00123 BOOST_STATIC_ASSERT(sizeof(unsigned long) == sizeof(void*));
00124
00125 DBG_GUI_E << "Adding timer.\n";
00126
00127 do {
00128 ++id;
00129 } while(id == 0 || timers.find(id) != timers.end());
00130
00131 ttimer timer;
00132 timer.sdl_id = SDL_AddTimer(
00133 interval, timer_callback, reinterpret_cast<void*>(id));
00134 if(timer.sdl_id == NULL) {
00135 WRN_GUI_E << "Failed to create an sdl timer.\n";
00136 return 0;
00137 }
00138
00139 if(repeat) {
00140 timer.interval = interval;
00141 }
00142
00143 timer.callback = callback;
00144
00145 timers.insert(std::make_pair(id, timer));
00146
00147 DBG_GUI_E << "Added timer " << id << ".\n";
00148 return id;
00149 }
00150
00151 bool
00152 remove_timer(const unsigned long id)
00153 {
00154 DBG_GUI_E << "Removing timer " << id << ".\n";
00155
00156 std::map<unsigned long, ttimer>::iterator itor = timers.find(id);
00157 if(itor == timers.end()) {
00158 LOG_GUI_E << "Can't remove timer since it no longer exists.\n";
00159 return false;
00160 }
00161
00162 if(id == executing_id) {
00163 executing_id_removed = true;
00164 return true;
00165 }
00166
00167 if(!SDL_RemoveTimer(itor->second.sdl_id)) {
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 DBG_GUI_E << "The timer is already out of the SDL timer list.\n";
00178 }
00179 timers.erase(itor);
00180 return true;
00181 }
00182
00183 bool
00184 execute_timer(const unsigned long id)
00185 {
00186 DBG_GUI_E << "Executing timer " << id << ".\n";
00187
00188 std::map<unsigned long, ttimer>::iterator itor = timers.find(id);
00189 if(itor == timers.end()) {
00190 LOG_GUI_E << "Can't execute timer since it no longer exists.\n";
00191 return false;
00192 }
00193
00194 {
00195 texecutor executor(id);
00196 itor->second.callback(id);
00197 }
00198
00199 if(!executing_id_removed && itor->second.interval == 0) {
00200 timers.erase(itor);
00201 }
00202 return true;
00203 }
00204
00205 }
00206