Wiselib
wiselib.testing/algorithms/topology/kneigh/kneigh_symmetric_topology_control.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: Juan Farré, jafarre@lsi.upc.edu                               **
00020  ***************************************************************************/
00021 #ifndef __ALGORITHMS_TOPOLOGY_KNEIGH_SYMMETRIC_TOPOLOGY_CONTROL_H__
00022 #define __ALGORITHMS_TOPOLOGY_KNEIGH_SYMMETRIC_TOPOLOGY_CONTROL_H__
00023 
00024 #include "algorithms/topology/topology_control_base.h"
00025 #include "algorithms/topology/kneigh/kneigh_broadcast_message.h"
00026 #include "algorithms/topology/kneigh/kneigh_list_message.h"
00027 #include "algorithms/topology/kneigh/kneigh_types.h"
00028 #include "util/pstl/algorithm.h"
00029 #include "util/pstl/pair.h"
00030 #include "util/pstl/vector_static.h"
00031 
00032 namespace wiselib {
00033 
00034 #define DELTA_DEF 60000
00035 #define D_DEF 16000
00036 #define TAU_DEF 1000
00037 #define PRUNE_DEF false
00038 #define ALPHA_DEF 2
00039 
00045 template<class OsModel_P, typename OsModel_P::size_t K = 9,
00046 //            class DistanceAlg_P,
00047       class Distance_P=uint16_t,
00048       class Radio_P = typename OsModel_P::Radio,
00049       class Timer_P = typename OsModel_P::Timer,
00050       class Rand_P = typename OsModel_P::Rand>
00051       class KneighProtocol: public TopologyBase<OsModel_P>
00052       {
00053       public:
00054          typedef OsModel_P OsModel;
00055          //      typedef DistanceAlg_P DistanceAlg;
00056       typedef Distance_P Distance;
00057       typedef Radio_P Radio;
00058       typedef Timer_P Timer;
00059       typedef Rand_P Rand;
00060 #ifdef DEBUG
00061       typedef typename OsModel_P::Debug Debug;
00062 #endif
00063 
00064       typedef KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P> self_type;
00065 
00066       typedef typename Radio::node_id_t node_id_t;
00067       typedef typename Radio::size_t size_t;
00068       typedef typename Radio::block_data_t block_data_t;
00069       typedef typename Radio::ExtendedData ExtendedData;
00070 
00071       typedef typename Timer::millis_t millis_t;
00072       typedef vector_static<OsModel,node_id_t,K> Neighbors;
00073 
00076       KneighProtocol();
00078 
00081       void enable();
00082       void disable();
00084 
00085       Neighbors &topology();
00086 
00087       void set_delta(register millis_t const delta=s_delta_def) {
00088          if(!d_enabled)
00089          d_delta=delta;
00090       }
00091 
00092       millis_t delta() const {
00093          return d_delta;
00094       }
00095 
00096       void set_d(register millis_t const d=s_d_def) {
00097          if(!d_enabled)
00098          d_d=d;
00099       }
00100 
00101       millis_t d() const {
00102          return d_d;
00103       }
00104 
00105       void set_tau(register millis_t const tau=s_tau_def) {
00106          if(!d_enabled)
00107          d_tau=tau;
00108       }
00109 
00110       millis_t tau() const {
00111          return d_tau;
00112       }
00113 
00114       void set_prune(register bool const prune=s_prune_def) {
00115          if(!d_enabled)
00116          d_prune=prune;
00117       }
00118 
00119       bool prune() const {
00120          return d_prune;
00121       }
00122 
00123       void set_alpha(register int const alpha=s_alpha_def) {
00124          if(!d_enabled)
00125          d_alpha=alpha;
00126       }
00127 
00128       int alpha() const {
00129          return d_alpha;
00130       }
00131 
00132       static void set_default_delta(millis_t const delta=DELTA_DEF) {
00133          s_delta_def=delta;
00134       }
00135 
00136       static millis_t default_delta() {
00137          return s_delta_def;
00138       }
00139 
00140       static void set_default_d(millis_t const d=D_DEF) {
00141          s_d_def=d;
00142       }
00143 
00144       static millis_t default_d() {
00145          return s_d_def;
00146       }
00147 
00148       static void set_default_tau(millis_t const tau=TAU_DEF) {
00149          s_tau_def=tau;
00150       }
00151 
00152       static millis_t default_tau() {
00153          return s_tau_def;
00154       }
00155 
00156       static void set_default_prune(bool const prune=PRUNE_DEF) {
00157          s_prune_def=prune;
00158       }
00159 
00160       static bool default_prune() {
00161          return s_prune_def;
00162       }
00163 
00164       static void set_default_alpha(int const alpha=ALPHA_DEF) {
00165          s_alpha_def=alpha;
00166       }
00167 
00168       static int default_alpha() {
00169          return s_alpha_def;
00170       }
00171 
00172 #ifdef DEBUG
00173       void init( Radio& radio, Timer& timer, Debug& debug ) {
00174          radio_ = &radio;
00175          timer_ = &timer;
00176          debug_ = &debug;
00177       }
00178 #else
00179       void init( Radio& radio, Timer& timer) {
00180          radio_ = &radio;
00181          timer_ = &timer;
00182       }
00183 #endif
00184 
00185       void destruct() {
00186       }
00187 
00188    private:
00189       Radio& radio()
00190       {  return *radio_;}
00191 
00192       Timer& timer()
00193       {  return *timer_;}
00194 
00195 #ifdef DEBUG
00196       Debug& debug()
00197       {  return *debug_;}
00198 #endif
00199 
00200       Radio * radio_;
00201       Timer * timer_;
00202 #ifdef DEBUG
00203       Debug * debug_;
00204 #endif
00205 
00206       typedef pair<node_id_t,Distance> ListEntry;
00207       typedef vector_static<OsModel,ListEntry,K> NodeList;
00208 
00209       class CompareListEntries {
00210       public:
00211          bool operator()(ListEntry left, ListEntry right) {
00212             return left.second<right.second;
00213          }
00214       };
00215 
00218       void timer0( void * const userdata );
00219       void timer1( void * const userdata );
00220       void timer2( void * const userdata );
00221       void timer3( void * const userdata );
00223 
00226       void receive( node_id_t from, size_t len, block_data_t *data, ExtendedData const &extended );
00228 
00229       bool d_enabled;
00230       millis_t d_delta;
00231       millis_t d_d;
00232       millis_t d_tau;
00233       bool d_prune;
00234       int d_alpha;
00235 
00236       NodeList list;
00237       Neighbors neigh;
00238       //      DistanceAlg dist_alg;
00239       Rand rand_gen;
00240 
00241       KNeighBroadcastMessage<OsModel,Radio> broadcast_msg;
00242       KNeighListMessage<OsModel,K,Radio> list_msg;
00243 
00244       static millis_t s_delta_def;
00245       static millis_t s_d_def;
00246       static millis_t s_tau_def;
00247       static bool s_prune_def;
00248       static int s_alpha_def;
00249    };
00250    // -----------------------------------------------------------------------
00251    // -----------------------------------------------------------------------
00252    template<class OsModel_P,
00253    typename OsModel_P::size_t K,
00254    //            class DistanceAlg_P,
00255    class Distance_P,
00256    class Radio_P,
00257    class Timer_P,
00258    class Rand_P>
00259    typename Timer_P::millis_t KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::s_delta_def=DELTA_DEF;
00260 
00261    template<class OsModel_P,
00262    typename OsModel_P::size_t K,
00263    //            class DistanceAlg_P,
00264    class Distance_P,
00265    class Radio_P,
00266    class Timer_P,
00267    class Rand_P>
00268    typename Timer_P::millis_t KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::s_d_def=D_DEF;
00269 
00270    template<class OsModel_P,
00271    typename OsModel_P::size_t K,
00272    //            class DistanceAlg_P,
00273    class Distance_P,
00274    class Radio_P,
00275    class Timer_P,
00276    class Rand_P>
00277    typename Timer_P::millis_t KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::s_tau_def=TAU_DEF;
00278 
00279    template<class OsModel_P,
00280    typename OsModel_P::size_t K,
00281    //            class DistanceAlg_P,
00282    class Distance_P,
00283    class Radio_P,
00284    class Timer_P,
00285    class Rand_P>
00286    bool KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::s_prune_def=PRUNE_DEF;
00287 
00288    template<class OsModel_P,
00289    typename OsModel_P::size_t K,
00290    //            class DistanceAlg_P,
00291    class Distance_P,
00292    class Radio_P,
00293    class Timer_P,
00294    class Rand_P>
00295    int KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::s_alpha_def=ALPHA_DEF;
00296    // -----------------------------------------------------------------------
00297    template<class OsModel_P,
00298    typename OsModel_P::size_t K,
00299    //            class DistanceAlg_P,
00300    class Distance_P,
00301    class Radio_P,
00302    class Timer_P,
00303    class Rand_P>
00304    KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::
00305 	KneighProtocol()
00306    : d_enabled(false),
00307    d_delta(s_delta_def),
00308    d_d(s_d_def),
00309    d_tau(s_tau_def),
00310    d_prune(s_prune_def),
00311    d_alpha(s_alpha_def)
00312    {
00313    };
00314    // -----------------------------------------------------------------------
00315    template<class OsModel_P,
00316    typename OsModel_P::size_t K,
00317    //            class DistanceAlg_P,
00318    class Distance_P,
00319    class Radio_P,
00320    class Timer_P,
00321    class Rand_P>
00322    void
00323    KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::
00324 	enable( void )
00325    {
00326       d_enabled=true;
00327       rand_gen.srand(radio().id());
00328       radio().template reg_recv_callback<self_type, &self_type::receive>( this );
00329       timer().template set_timer<self_type, &self_type::timer0>(
00330             delta()+rand_gen(d()), this, 0 );
00331       //      dist_alg.enable();
00332       neigh.clear();
00333       list.clear();
00334 #ifdef DEBUG
00335       debug().debug( "KneighProtocol Boots for %i\n", radio().id() );
00336 #endif
00337    }
00338    // -----------------------------------------------------------------------
00339    template<class OsModel_P,
00340    typename OsModel_P::size_t K,
00341    //            class DistanceAlg_P,
00342    class Distance_P,
00343    class Radio_P,
00344    class Timer_P,
00345    class Rand_P>
00346    void
00347    KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::
00348 	disable( void )
00349    {
00350 #ifdef DEBUG
00351       debug().debug( "Called KneighProtocol::disable\n" );
00352 #endif
00353       d_enabled=false;
00354    }
00355    // -----------------------------------------------------------------------
00356    template<class OsModel_P,
00357    typename OsModel_P::size_t K,
00358    //            class DistanceAlg_P,
00359    class Distance_P,
00360    class Radio_P,
00361    class Timer_P,
00362    class Rand_P>
00363    typename KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::Neighbors &
00364    KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::topology()
00365    {
00366       return neigh;
00367    }
00368    // -----------------------------------------------------------------------
00369    template<class OsModel_P,
00370    typename OsModel_P::size_t K,
00371    //            class DistanceAlg_P,
00372    class Distance_P,
00373    class Radio_P,
00374    class Timer_P,
00375    class Rand_P>
00376    void
00377    KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::
00378 	timer0( void* userdata )
00379    {
00380 #ifdef DEBUG
00381       debug().debug( "Timer0 elapsed\n");
00382 #endif
00383       if(!d_enabled)
00384       return;
00385       broadcast_msg.set_msg_id(KNeighBroadcastMsgId);
00386       radio().send( radio().BROADCAST_ADDRESS, broadcast_msg.buffer_size(), broadcast_msg.buf() );
00387       timer().template set_timer<self_type, &self_type::timer1>(
00388             delta()+d(), this, 0 );
00389 #ifdef DEBUG
00390       debug().debug( "Broadcast message sent\n");
00391 #endif
00392    }
00393 
00394    template<class OsModel_P,
00395    typename OsModel_P::size_t K,
00396    //            class DistanceAlg_P,
00397    class Distance_P,
00398    class Radio_P,
00399    class Timer_P,
00400    class Rand_P>
00401    void
00402    KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::
00403    timer1( void* userdata )
00404    {
00405 #ifdef DEBUG
00406       debug().debug( "Timer1 elapsed\n");
00407 #endif
00408       if(!d_enabled)
00409       return;
00410       list_msg.set_msg_id(KNeighListMsgId);
00411       list_msg.set_neighbor_number(list.size());
00412       for(size_t i=0;i<list.size();i++)
00413       list_msg.set_neighbor(i,list[i].first);
00414       timer().template set_timer<self_type, &self_type::timer2>(
00415             delta()+d()+tau()+rand_gen(d()), this, 0 );
00416 #ifdef DEBUG
00417       debug().debug( "First list generated\n");
00418 #endif
00419    }
00420 
00421    template<class OsModel_P,
00422    typename OsModel_P::size_t K,
00423    //            class DistanceAlg_P,
00424    class Distance_P,
00425    class Radio_P,
00426    class Timer_P,
00427    class Rand_P>
00428    void
00429    KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::
00430    timer2( void* userdata )
00431    {
00432 #ifdef DEBUG
00433       debug().debug( "Timer2 elapsed\n");
00434 #endif
00435       if(!d_enabled)
00436       return;
00437       radio().send( radio().BROADCAST_ADDRESS, list_msg.buffer_size(), list_msg.buf() );
00438       timer().template set_timer<self_type, &self_type::timer3>(
00439             delta()+2*d()+tau(), this, 0 );
00440 #ifdef DEBUG
00441       debug().debug( "List message sent\n");
00442 #endif
00443    }
00444 
00445    template<class OsModel_P,
00446    typename OsModel_P::size_t K,
00447    //            class DistanceAlg_P,
00448    class Distance_P,
00449    class Radio_P,
00450    class Timer_P,
00451    class Rand_P>
00452    void
00453    KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::
00454    timer3( void* userdata )
00455    {
00456 #ifdef DEBUG
00457       debug().debug( "Timer3 elapsed\n");
00458 #endif
00459       if(!d_enabled)
00460       return;
00461 #ifdef DEBUG
00462       debug().debug( "%d neighbors for node %i:\n",neigh.size(),radio().id() );
00463       for(size_t i=0;i<neigh.size();i++)
00464       debug().debug("%i\n",neigh[i]);
00465 #endif
00466       TopologyBase<OsModel>::notify_listeners();
00467    }
00468    // -----------------------------------------------------------------------
00469    template<class OsModel_P,
00470    typename OsModel_P::size_t K,
00471    //            class DistanceAlg_P,
00472    class Distance_P,
00473    class Radio_P,
00474    class Timer_P,
00475    class Rand_P>
00476    void
00477    KneighProtocol<OsModel_P, K, Distance_P, Radio_P, Timer_P, Rand_P>::
00478    receive( node_id_t from, size_t len, block_data_t *data, ExtendedData const &extended )
00479    {
00480       typedef typename NodeList::iterator Iter;
00481       switch(*data) {
00482          case KNeighBroadcastMsgId: {
00483 #ifdef DEBUG
00484       debug().debug( "Broadcast message received\n");
00485 #endif
00486       ListEntry const entry(from,extended.link_metric());
00487       if(list.size()<K) {
00488          list.push_back(entry);
00489          if(list.size()==1)
00490          return;
00491       }
00492       else if(entry.second>=list[K-1].second)
00493       return;
00494       linear_insert(list.begin(),list.end()-1,entry,CompareListEntries());
00495    }
00496    break;
00497    case KNeighListMsgId: {
00498 #ifdef DEBUG
00499       debug().debug( "List message received\n");
00500 #endif
00501       Iter i=list.begin();
00502       for(;i!=list.end()&&i->first!=from;i++);
00503       if(i!=list.end()) {
00504          KNeighListMessage<OsModel,K,Radio> *const m=reinterpret_cast<KNeighListMessage<OsModel,K,Radio> *>(data);
00505          uint8_t j=0;
00506          for(;j<m->neighbor_number()&&m->neighbor(j)!=radio().id();j++);
00507          if(j<m->neighbor_number()) {
00508             neigh.push_back(from);
00509          }
00510       }
00511    }
00512    break;
00513 }
00514 }
00515 
00516 }
00517 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines