X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flibr2c2%2Flayout.cpp;h=fe21881a2e4ab46a5f7f1e3b6a6e48c75bf7c2af;hb=08dea8dfcf923e9296bcd3910455540895d0439b;hp=0901382b91d0f140bb8ddf39010bf41228b33bfb;hpb=81ee4fbd16b472892b67b35ea85956423a2247ed;p=r2c2.git diff --git a/source/libr2c2/layout.cpp b/source/libr2c2/layout.cpp index 0901382..fe21881 100644 --- a/source/libr2c2/layout.cpp +++ b/source/libr2c2/layout.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -40,7 +41,8 @@ namespace R2C2 { Layout::Layout(Catalogue &c, Driver *d): catalogue(c), driver(d), - next_turnout_addr(0x800) + next_turnout_addr(0x800), + emitting_block_reserved(false) { clock.set_rate(60); } @@ -69,31 +71,69 @@ Driver &Layout::get_driver() const void Layout::add(Object &o) { if(objects.insert(o)) - signal_object_added.emit(o); + { + try + { + signal_object_added.emit(o); + } + catch(...) + { + objects.erase(o); + throw; + } + } } void Layout::add(Track &t) { if(objects.insert(t)) { - // Blocks must be recreated first - create_blocks(); - signal_object_added.emit(t); + try + { + // Blocks must be recreated first + create_blocks(); + signal_object_added.emit(t); + } + catch(...) + { + objects.erase(t); + create_blocks(); + throw; + } } } void Layout::add(TrackChain &g) { if(track_chains.insert(g)) - signal_track_chain_added.emit(g); + { + try + { + signal_track_chain_added.emit(g); + } + catch(...) + { + track_chains.erase(g); + throw; + } + } } void Layout::add(Block &b) { if(track_chains.insert(b)) { - b.signal_reserved.connect(sigc::bind<0>(signal_block_reserved, sigc::ref(b))); - signal_track_chain_added.emit(b); + sigc::connection conn = b.signal_reserved.connect(sigc::bind<0>(sigc::mem_fun(this, &Layout::block_reserved), sigc::ref(b))); + try + { + signal_track_chain_added.emit(b); + } + catch(...) + { + track_chains.erase(b); + conn.disconnect(); + throw; + } } } @@ -485,7 +525,12 @@ void Layout::save_dynamic(const string &fn) const const set &tracks = objects.get(); for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) if((*i)->get_type().is_turnout()) - writer.write((DataFile::Statement("turnout"), (*i)->get_turnout_address(), (*i)->get_active_path())); + { + DataFile::Statement st("turnout"); + st.append((*i)->get_turnout_address()); + (*i)->save_dynamic(st.sub); + writer.write(st); + } for(map::const_iterator i=trains.begin(); i!=trains.end(); ++i) { @@ -508,6 +553,23 @@ void Layout::sensor_state_changed(Sensor &sensor, Sensor::State state) } } +void Layout::block_reserved(Block &block, Train *train) +{ + if(emitting_block_reserved) + block_reserve_queue.push_back(BlockReservation(block, train)); + else + { + SetFlag setf(emitting_block_reserved); + signal_block_reserved.emit(block, train); + while(!block_reserve_queue.empty()) + { + BlockReservation br = block_reserve_queue.front(); + block_reserve_queue.pop_front(); + signal_block_reserved.emit(br.block, br.train); + } + } +} + template Layout::Storage::~Storage() @@ -562,6 +624,12 @@ void Layout::Storage::del() } +Layout::BlockReservation::BlockReservation(Block &b, Train *t): + block(b), + train(t) +{ } + + Layout::Loader::Loader(Layout &l): DataFile::ObjectLoader(l) { @@ -575,6 +643,9 @@ Layout::Loader::Loader(Layout &l): add("train", &Loader::train); add("turnout", &Loader::turnout); add("zone", &Loader::zone); + + // Deprecated + add("turnout", &Loader::turnout2); } void Layout::Loader::beamgate() @@ -622,8 +693,24 @@ void Layout::Loader::train(const string &n, unsigned addr, const std::string &pr load_sub(*trn); } -void Layout::Loader::turnout(unsigned addr, unsigned path) +void Layout::Loader::turnout(unsigned addr) +{ + /* Kinda slow, but maintaining a map of turnouts seems more trouble than + it's worth at this point. */ + const set &tracks = obj.objects.get(); + for(set::const_iterator i=tracks.begin(); i!=tracks.end(); ++i) + if((*i)->get_turnout_address()==addr) + { + load_sub(**i); + return; + } + + throw key_error(addr); +} + +void Layout::Loader::turnout2(unsigned addr, unsigned path) { + // XXX Discrepancy between ids and addresses if(obj.driver) obj.driver->set_turnout(addr, path); }