Wiselib
wiselib.testing/algorithms/graph/dbfs/dbfs_graph.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines