Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "map-manager.h"
00035
00036 #include "common/wave_ex.h"
00037
00038 #include "threadsafe/smart_mutex.h"
00039 #include "threadsafe/threadsafe_queue.h"
00040
00041
00042 namespace aesop {
00043
00044
00045 MapManager::~MapManager(void) throw() { }
00046
00047
00048 static const useconds_t s_sleepMicroseconds = 2000;
00049
00050
00051
00053
00054
00055
00057
00058 class MapMgr : public MapManager {
00059 public:
00060 MapMgr(void) throw();
00061 ~MapMgr(void) throw() { }
00062
00063
00064 void initialize(IN smart_ptr<Datahash>& params,
00065 IN smart_ptr<story::Story>& story);
00066
00067
00068 void clear(void);
00069 void requestLoad(IN const char * id);
00070 smart_ptr<MapDynamics> getMap(IN const char * id);
00071 void tickMaps(IN float seconds);
00072 void getIterator(OUT iterator_t& i);
00073 bool getNextMap(IO iterator_t& i,
00074 OUT smart_ptr<MapDynamics>& map);
00075
00076 private:
00077
00078 typedef std::map<std::string, smart_ptr<MapDynamics> > id_map_t;
00079
00080 typedef threadsafe_queue<std::string> id_queue_t;
00081
00082 struct real_iter_t {
00083 dword_t rvn;
00084 id_map_t::iterator iter;
00085 };
00086
00087
00088 void doThread(void);
00089 static void * threadStart(void *);
00090 static real_iter_t * getRealIterator(IN iterator_t& i) throw()
00091 { return (real_iter_t *) &i; }
00092
00093
00094 smart_mutex m_mutex;
00095 smart_ptr<Datahash> m_params;
00096 smart_ptr<story::Story> m_story;
00097 id_queue_t m_loadQueue;
00098 pthread_t m_thread;
00099 id_map_t m_maps;
00100 dword_t m_rvn;
00101 };
00102
00103
00104
00105 MapMgr::MapMgr(void)
00106 throw()
00107 {
00108 m_rvn = 4381;
00109 }
00110
00111
00112
00113 void
00114 MapMgr::initialize
00115 (
00116 IN smart_ptr<Datahash>& params,
00117 IN smart_ptr<story::Story>& story
00118 )
00119 {
00120 ASSERT(params, "null");
00121 ASSERT(story, "null");
00122
00123 m_params = params;
00124 m_story = story;
00125
00126
00127 ASSERT(!pthread_create(&m_thread, NULL, threadStart, this),
00128 "Failed to create map manager worker thread");
00129 DPRINTF("Thread id = 0x%08lx", m_thread);
00130 }
00131
00132
00133
00135
00136
00137
00139
00140 void
00141 MapMgr::clear
00142 (
00143 void
00144 )
00145 {
00146 DPRINTF("WARNING: requested to clear all map state!");
00147
00148
00149 mlock l(m_mutex);
00150 ++m_rvn;
00151 m_maps.clear();
00152 }
00153
00154
00155
00156 void
00157 MapMgr::requestLoad
00158 (
00159 IN const char * id
00160 )
00161 {
00162 ASSERT(id, "null");
00163 ASSERT(m_story, "null");
00164
00165 std::string str_id = id;
00166
00167
00168 m_loadQueue.push_back(str_id);
00169 }
00170
00171
00172
00173 smart_ptr<MapDynamics>
00174 MapMgr::getMap
00175 (
00176 IN const char * id
00177 )
00178 {
00179 ASSERT(id, "null");
00180
00181
00182 mlock l(m_mutex);
00183
00184
00185 id_map_t::iterator i = m_maps.find(id);
00186 if (m_maps.end() == i) {
00187 DPRINTF("No such map!");
00188 return NULL;
00189 }
00190 ASSERT(i->second, "null");
00191
00192 return i->second;
00193 }
00194
00195
00196
00197 void
00198 MapMgr::tickMaps
00199 (
00200 IN float seconds
00201 )
00202 {
00203 ASSERT(seconds > 0, "Bad seconds: %f", seconds);
00204
00205
00206 mlock l(m_mutex);
00207
00208
00209 for (id_map_t::iterator i = m_maps.begin(); i != m_maps.end(); ++i) {
00210 MapDynamics * md = i->second;
00211 ASSERT(md, "null");
00212
00213 md->tickMap(seconds);
00214 }
00215 }
00216
00217
00218
00219 void
00220 MapMgr::getIterator
00221 (
00222 OUT iterator_t& i
00223 )
00224 {
00225 real_iter_t * ri = getRealIterator(i);
00226
00227
00228 mlock l(m_mutex);
00229 ri->rvn = m_rvn;
00230 ri->iter = m_maps.begin();
00231 }
00232
00233
00234
00235 bool
00236 MapMgr::getNextMap
00237 (
00238 IO iterator_t& i,
00239 OUT smart_ptr<MapDynamics>& map
00240 )
00241 {
00242 map = NULL;
00243 real_iter_t * ri = getRealIterator(i);
00244
00245
00246 mlock l(m_mutex);
00247
00248 if (m_rvn != ri->rvn)
00249 return false;
00250
00251 if (m_maps.end() == ri->iter)
00252 return false;
00253
00254
00255 map = ri->iter->second;
00256 ASSERT(map, "null dynamics object?");
00257 ++ri->iter;
00258 return true;
00259 }
00260
00261
00262
00264
00265
00266
00268
00269 void
00270 MapMgr::doThread
00271 (
00272 void
00273 )
00274 {
00275
00276 for (;;) {
00277 usleep(s_sleepMicroseconds);
00278
00279
00280 std::string id;
00281 if (!m_loadQueue.pop_front(id))
00282 continue;
00283
00284
00285
00286 std::string path;
00287 {
00288 mlock l(m_mutex);
00289 if (m_maps.end() != m_maps.find(id)) {
00290
00291 continue;
00292 }
00293
00294
00295 path = m_story->getObjectPath("map", id.c_str());
00296 }
00297
00298
00299 DPRINTF("******* Loading map: %s", id.c_str());
00300 smart_ptr<Map> map = loadMap(id.c_str(), path.c_str());
00301 ASSERT(map, "null");
00302
00303 smart_ptr<MapDynamics> dyn = MapDynamics::create(map, m_params);
00304 ASSERT(dyn, "null");
00305
00306
00307 {
00308 mlock l(m_mutex);
00309 ++m_rvn;
00310 m_maps[id] = dyn;
00311 }
00312 }
00313 }
00314
00315
00316
00317 void *
00318 MapMgr::threadStart
00319 (
00320 IN void * ctx
00321 )
00322 {
00323 MapMgr * pThis = (MapMgr *) ctx;
00324 for (;;) {
00325 try {
00326 pThis->doThread();
00327 } catch (std::exception& e) {
00328 DPRINTF("Exception from MapMgr worker thread:\n %s",
00329 e.what());
00330 }
00331 }
00332 return NULL;
00333 }
00334
00335
00336
00338
00339
00340
00342
00343 smart_ptr<MapManager>
00344 MapManager::create
00345 (
00346 IN smart_ptr<Datahash>& params,
00347 IN smart_ptr<story::Story>& story
00348 )
00349 {
00350 ASSERT(params, "null");
00351 ASSERT(story, "null");
00352
00353 smart_ptr<MapMgr> local = new MapMgr;
00354 ASSERT(local, "out of memory");
00355
00356 local->initialize(params, story);
00357
00358 return local;
00359 }
00360
00361
00362
00363 };
00364