Wiselib
|
00001 /*************************************************************************** 00002 ** This file is part of the generic algorithm library Wiselib. ** 00003 ** Copyright (C) 2008,2009 by the Wisebed (www.wisebed.eu) project. ** 00004 ** ** 00005 ** The Wiselib is free software: you can redistribute it and/or modify ** 00006 ** it under the terms of the GNU Lesser General Public License as ** 00007 ** published by the Free Software Foundation, either version 3 of the ** 00008 ** License, or (at your option) any later version. ** 00009 ** ** 00010 ** The Wiselib is distributed in the hope that it will be useful, ** 00011 ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** 00012 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** 00013 ** GNU Lesser General Public License for more details. ** 00014 ** ** 00015 ** You should have received a copy of the GNU Lesser General Public ** 00016 ** License along with the Wiselib. ** 00017 ** If not, see <http://www.gnu.org/licenses/>. ** 00018 ** ** 00019 ** Author: Víctor López Ferrando, victorlopez90@gmail.com ** 00020 ***************************************************************************/ 00021 #ifndef __ALGORITHMS_GRAPH_DBFS_GRAPH_H__ 00022 #define __ALGORITHMS_GRAPH_DBFS_GRAPH_H__ 00023 00024 #include "util/delegates/delegate.hpp" 00025 #include "util/pstl/vector_static.h" 00026 00027 #define DEBUG_DBFS_GRAPH 00028 00029 namespace wiselib 00030 { 00031 00039 template<typename OsModel_P, 00040 typename Radio_P = typename OsModel_P::Radio, 00041 typename Debug_P = typename OsModel_P::Debug, 00042 uint16_t MAX_NODES = 32> 00043 class DbfsGraph 00044 { 00045 public: 00046 typedef OsModel_P OsModel; 00047 typedef Radio_P Radio; 00048 typedef Debug_P Debug; 00049 00050 typedef typename OsModel_P::Timer Timer; 00051 00052 typedef DbfsGraph<OsModel, Radio, Debug, MAX_NODES> self_type; 00053 00054 typedef typename Radio::node_id_t node_id_t; 00055 typedef typename Radio::size_t size_t; 00056 typedef typename Radio::block_data_t block_data_t; 00057 00058 typedef typename Timer::millis_t millis_t; 00059 00060 typedef delegate0<void> dbfs_delegate_t; 00061 00064 uint8_t level_; 00065 node_id_t parent_; 00066 vector_static<OsModel, node_id_t, MAX_NODES> children_; 00068 00071 DbfsGraph(); 00072 ~DbfsGraph(); 00074 00077 void enable( void ); 00078 void disable( void ); 00079 inline void set_root( void ) 00080 { root_ = true; } 00082 00085 void timer0( void *userdata ); 00086 void timer1( void *userdata ); 00088 00091 void receive( node_id_t from, size_t len, block_data_t *data ); 00093 00094 inline void set_startup_time( millis_t startup_time ) 00095 { startup_time_ = startup_time; }; 00096 00097 inline void set_neighbourhood_construction_time( millis_t neighbourhood_construction_time ) 00098 { neighbourhood_construction_time_ = neighbourhood_construction_time; }; 00099 00100 template<class T, void (T::*TMethod)()> 00101 inline void reg_finish_callback( T *obj_pnt ) 00102 { 00103 dbfs_delegate_ = dbfs_delegate_t::from_method<T, TMethod>( obj_pnt ); 00104 set_dbfs_delegate_ = true; 00105 }; 00106 00107 void init( Radio& radio, Timer& timer, Debug& debug ) { 00108 radio_ = &radio; 00109 timer_ = &timer; 00110 debug_ = &debug; 00111 } 00112 00113 void destruct() { 00114 } 00115 00116 private: 00117 Radio& radio() 00118 { return *radio_; } 00119 00120 Timer& timer() 00121 { return *timer_; } 00122 00123 Debug& debug() 00124 { return *debug_; } 00125 00126 Radio * radio_; 00127 Timer * timer_; 00128 Debug * debug_; 00129 00132 // TODO: standarize msg ids 00133 enum DbfsGraphMsgIds { 00134 DbfsMsgIdLabel = 130, 00135 DbfsMsgIdEcho = 131, 00136 DbfsMsgIdNeighbourhood = 132, 00137 EchoKeepon = 0, 00138 EchoStop = 1, 00139 EchoEnd = 2, 00140 }; 00141 00142 uint8_t message_[2]; 00143 00144 bool root_; 00145 millis_t startup_time_, neighbourhood_construction_time_; 00146 00147 bool set_dbfs_delegate_; 00148 dbfs_delegate_t dbfs_delegate_; 00149 00150 bool labeled_; 00151 00152 vector_static<OsModel, node_id_t, MAX_NODES> neighbours_; 00153 vector_static<OsModel, node_id_t, MAX_NODES> send_to_; 00154 vector_static<OsModel, bool, MAX_NODES> echoed_; 00155 00156 }; 00157 // ----------------------------------------------------------------------- 00158 // ----------------------------------------------------------------------- 00159 // ----------------------------------------------------------------------- 00160 template<typename OsModel_P, 00161 typename Radio_P, 00162 typename Debug_P, 00163 uint16_t MAX_NODES> 00164 DbfsGraph<OsModel_P, Radio_P, Debug_P, MAX_NODES>:: 00165 DbfsGraph() 00166 : root_ ( false ), 00167 startup_time_ ( 2000 ), 00168 neighbourhood_construction_time_ ( 3000 ), 00169 set_dbfs_delegate_ ( false ) 00170 {}; 00171 // ----------------------------------------------------------------------- 00172 template<typename OsModel_P, 00173 typename Radio_P, 00174 typename Debug_P, 00175 uint16_t MAX_NODES> 00176 DbfsGraph<OsModel_P, Radio_P, Debug_P, MAX_NODES>:: 00177 ~DbfsGraph() 00178 { 00179 #ifdef DEBUG_DBFS_GRAPH 00180 // debug().debug( "%i: DbfsGraph Destroyed\n", radio().id() ); 00181 #endif 00182 }; 00183 // ----------------------------------------------------------------------- 00184 template<typename OsModel_P, 00185 typename Radio_P, 00186 typename Debug_P, 00187 uint16_t MAX_NODES> 00188 void 00189 DbfsGraph<OsModel_P, Radio_P, Debug_P, MAX_NODES>:: 00190 enable( void ) 00191 { 00192 labeled_ = false; 00193 radio().enable_radio(); 00194 radio().template reg_recv_callback<self_type, &self_type::receive>( 00195 this ); 00196 parent_ = -1; 00197 timer().template set_timer<self_type, &self_type::timer0>( 00198 startup_time_, this, 0 ); 00199 } 00200 // ----------------------------------------------------------------------- 00201 template<typename OsModel_P, 00202 typename Radio_P, 00203 typename Debug_P, 00204 uint16_t MAX_NODES> 00205 void 00206 DbfsGraph<OsModel_P, Radio_P, Debug_P, MAX_NODES>:: 00207 disable( void ) 00208 { 00209 #ifdef DEBUG_DBFS_GRAPH 00210 debug().debug( "%i: Called DbfsGraph::disable\n", radio().id() ); 00211 #endif 00212 } 00213 // ----------------------------------------------------------------------- 00214 template<typename OsModel_P, 00215 typename Radio_P, 00216 typename Debug_P, 00217 uint16_t MAX_NODES> 00218 void 00219 DbfsGraph<OsModel_P, Radio_P, Debug_P, MAX_NODES>:: 00220 timer0( void* userdata ) 00221 { 00222 #ifdef DEBUG_DBFS_GRAPH 00223 debug().debug( "%i: Executing Timer0 'DbfsGraph'\n", radio().id() ); 00224 #endif 00225 message_[0] = DbfsMsgIdNeighbourhood; 00226 radio().send( radio().BROADCAST_ADDRESS, 1, (uint8_t*)&message_ ); 00227 if ( root_ ) 00228 { 00229 timer().template set_timer<self_type, &self_type::timer1>( 00230 neighbourhood_construction_time_, this, 0 ); 00231 } 00232 } 00233 // ----------------------------------------------------------------------- 00234 template<typename OsModel_P, 00235 typename Radio_P, 00236 typename Debug_P, 00237 uint16_t MAX_NODES> 00238 void 00239 DbfsGraph<OsModel_P, Radio_P, Debug_P, MAX_NODES>:: 00240 timer1( void* userdata ) 00241 { 00242 #ifdef DEBUG_DBFS_GRAPH 00243 debug().debug( "%i: Executing TimerElapsed 'DbfsGraph'\n", radio().id() ); 00244 #endif 00245 // Root inits the algorithm 00246 labeled_ = true; 00247 parent_ = radio().id(); 00248 level_ = 0; 00249 send_to_ = neighbours_; 00250 echoed_.clear(); 00251 for (int i = 0; i < (int)send_to_.size(); ++i) 00252 echoed_.push_back(false); 00253 children_.clear(); 00254 if (send_to_.empty()) { 00255 #ifdef DEBUG_DBFS_GRAPH 00256 debug().debug( "%i: Stop of the algorithm\n", radio().id()); 00257 #endif 00258 if ( set_dbfs_delegate_ ) 00259 dbfs_delegate_(); 00260 } 00261 else { 00262 for (int i = 0; i < (int)send_to_.size(); ++i) { 00263 message_[0] = DbfsMsgIdLabel; 00264 message_[1] = level_; 00265 radio().send( send_to_[i], 2, (uint8_t*)&message_ ); 00266 echoed_[i] = false; 00267 } 00268 } 00269 } 00270 // ----------------------------------------------------------------------- 00271 template<typename OsModel_P, 00272 typename Radio_P, 00273 typename Debug_P, 00274 uint16_t MAX_NODES> 00275 void 00276 DbfsGraph<OsModel_P, Radio_P, Debug_P, MAX_NODES>:: 00277 receive( node_id_t from, size_t len, block_data_t *data ) 00278 { 00279 uint8_t msg_id = *data; 00280 if ( msg_id == DbfsMsgIdNeighbourhood and from != radio().id() ) 00281 { 00282 #ifdef DEBUG_DBFS_GRAPH 00283 debug().debug( "%i: It's a DbfsMsgIdNeighbourhood message from %i\n", radio().id(), from ); 00284 #endif 00285 neighbours_.push_back( from ); 00286 } 00287 else if ( msg_id == DbfsMsgIdLabel ) // I'm visited for the first time 00288 { 00289 #ifdef DEBUG_DBFS_GRAPH 00290 debug().debug( "%i: It's a DbfsMsgIdLabel message from %i\n", radio().id(), from ); 00291 #endif 00292 if (labeled_ == false) { 00293 labeled_ = true; 00294 parent_ = from; 00295 ++data; // TODO: volem el segon byte 00296 level_ = *data + 1; 00297 send_to_ = neighbours_; 00298 echoed_.clear(); 00299 for (int i = 0; i < (int)send_to_.size(); ++i) 00300 echoed_.push_back(false); 00301 for (int i = 0; i < (int)send_to_.size(); ++i) 00302 if (send_to_[i] == from) { 00303 send_to_.erase(send_to_.begin() + i); 00304 echoed_.erase(echoed_.begin() + i); 00305 } 00306 children_.clear(); 00307 message_[0] = DbfsMsgIdEcho; 00308 if (send_to_.empty()) 00309 message_[1] = EchoEnd; 00310 else 00311 message_[1] = EchoKeepon; 00312 radio().send( parent_, 2, (uint8_t*)&message_ ); 00313 } 00314 else { 00315 if (parent_ == from) { 00316 for (int i = 0; i < (int)send_to_.size(); ++i) { 00317 message_[0] = DbfsMsgIdLabel; 00318 message_[1] = level_; 00319 radio().send( send_to_[i], 2, (uint8_t*)&message_ ); 00320 echoed_[i] = false; 00321 } 00322 } 00323 else { 00324 message_[0] = DbfsMsgIdEcho; 00325 message_[1] = EchoStop; 00326 radio().send( from, 2, (uint8_t*)&message_ ); 00327 } 00328 } 00329 } 00330 else if ( msg_id == DbfsMsgIdEcho ) // the search is resumed from me, wich I've already been visited 00331 { 00332 #ifdef DEBUG_DBFS_GRAPH 00333 debug().debug( "%i: It's a DbfsMsgIdEcho message from %i\n", radio().id(), from ); 00334 #endif 00335 for (int i = 0; i < (int)send_to_.size(); ++i) 00336 if (send_to_[i] == from) 00337 echoed_[i] = true; 00338 uint8_t status = *(++data); // TODO: volem el segon byte 00339 if (status == EchoKeepon) { 00340 bool is_children = false; 00341 for (int i = 0; i < (int)children_.size() and not is_children; ++i) 00342 if (children_[i] == from) 00343 is_children = true; 00344 if (not is_children) 00345 children_.push_back(from); 00346 } 00347 else if (status == EchoStop) { 00348 for (int i = 0; i < (int)send_to_.size(); ++i) 00349 if (send_to_[i] == from) { 00350 send_to_.erase(send_to_.begin() + i); 00351 echoed_.erase(echoed_.begin() + i); 00352 } 00353 } 00354 else if (status == EchoEnd) { 00355 bool is_children = false; 00356 for (int i = 0; i < (int)children_.size() and not is_children; ++i) 00357 if (children_[i] == from) 00358 is_children = true; 00359 if (not is_children) 00360 children_.push_back(from); 00361 for (int i = 0; i < (int)send_to_.size(); ++i) 00362 if (send_to_[i] == from) { 00363 send_to_.erase(send_to_.begin() + i); 00364 echoed_.erase(echoed_.begin() + i); 00365 } 00366 } 00367 if (send_to_.empty()) { 00368 if (root_) { 00369 #ifdef DEBUG_DBFS_GRAPH 00370 debug().debug( "%i: Stop of the algorithm\n", radio().id(), from ); 00371 #endif 00372 if ( set_dbfs_delegate_ ) 00373 dbfs_delegate_(); 00374 } 00375 else { 00376 message_[0] = DbfsMsgIdEcho; 00377 message_[1] = EchoEnd; 00378 radio().send( parent_, 2, (uint8_t*)&message_ ); 00379 } 00380 } 00381 else { 00382 bool all_echoed = true; 00383 for (int i = 0; i < (int)echoed_.size() and all_echoed; ++i) 00384 if (not echoed_[i]) 00385 all_echoed = false; 00386 if (all_echoed) { 00387 if (root_) 00388 for (int i = 0; i < (int)send_to_.size(); ++i) { 00389 message_[0] = DbfsMsgIdLabel; 00390 message_[1] = level_; 00391 radio().send( send_to_[i], 2, (uint8_t*)&message_ ); 00392 echoed_[i] = false; 00393 } 00394 else { 00395 message_[0] = DbfsMsgIdEcho; 00396 message_[1] = EchoKeepon; 00397 radio().send( parent_, 2, (uint8_t*)&message_ ); 00398 } 00399 } 00400 } 00401 } 00402 } 00403 } 00404 #endif