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 #ifndef __ALGORITHMS_SYNCHRONIZATION_LTS_SYNCHRONIZATION_H__ 00020 #define __ALGORITHMS_SYNCHRONIZATION_LTS_SYNCHRONIZATION_H__ 00021 00022 #include "algorithms/synchronization/lts/lts_synchronization_message.h" 00023 #include "algorithms/graph/ddfs/ddfs_graph.h" 00024 #include "util/delegates/delegate.hpp" 00025 00026 #define DEBUG_LTS_SYNCHRONIZATION 00027 // #define DEBUG_LTS_SYNCHRONIZATION_SHAWN 00028 namespace wiselib 00029 { 00030 00031 template<typename OsModel_P, 00032 typename Radio_P = typename OsModel_P::Radio, 00033 typename Clock_P = typename OsModel_P::Clock, 00034 typename Debug_P = typename OsModel_P::Debug, 00035 typename NeighborhoodDiscovery_P = typename wiselib::DdfsGraph<OsModel_P, Radio_P, Debug_P, MAX_NODES>, 00036 uint16_t MAX_NODES = 32> 00037 class LtsSynchronization : public synchronizationBase<OsModel_P> 00038 { 00039 public: 00040 typedef OsModel_P OsModel; 00041 typedef Radio_P Radio; 00042 typedef Debug_P Debug; 00043 typedef Clock_P Clock; 00044 typedef typename Clock::time_t time_t; 00045 typedef NeighborhoodDiscovery_P NeighborhoodDiscovery; 00046 00047 typedef LtsSynchronization<OsModel, Radio, Debug, Clock, MAX_NODES, Neighborhood> self_type; 00048 typedef LtsSynchronizationMessage<OsModel, Radio, time_t> SynchronizationMessage; 00049 00050 typedef typename Radio::node_id_t node_id_t; 00051 typedef typename Radio::size_t size_t; 00052 typedef typename Radio::block_data_t block_data_t; 00053 00054 typedef delegate0<void> lts_delegate_t; 00055 00056 static const uint8_t TIME_SIZE = sizeof( Time ); 00057 00060 LtsSynchronization(); 00061 ~LtsSynchronization(); 00063 00066 void enable( void ); 00067 void disable( void ); 00068 inline void set_root( bool root ) 00069 { root_ = root; } 00071 00074 void receive( node_id_t from, size_t len, block_data_t *data ); 00076 00077 time_t time() 00078 { 00079 return clock().time(); 00080 } 00081 00082 void start_synchronization(); 00083 00084 void destruct() 00085 {} 00086 00087 private: 00088 Radio& radio() 00089 { return *radio_; } 00090 00091 Clock& clock() 00092 { return *clock_; } 00093 00094 Debug& debug() 00095 { return *debug_; } 00096 00097 NeighborhoodDiscovery& neighborhood_discovery() 00098 { return *neighborhood_discovery_; } 00099 00100 Radio * radio_; 00101 Clock * clock_; 00102 Debug * debug_; 00103 NeighborhoodDiscovery * neighborhood_discovery_; 00104 00107 enum LtsSynchronizationMsgIds { 00108 LtsMsgIdSynchronizationPulse = 150, 00109 LtsMsgIdAcknowledgement = 151, 00110 LtsMsgIdOffset = 152, 00111 }; 00112 00113 bool root_; 00114 00115 SynchronizationMessage synchronizationMessage; 00116 00117 }; 00118 // ----------------------------------------------------------------------- 00119 // ----------------------------------------------------------------------- 00120 // ----------------------------------------------------------------------- 00121 template<typename OsModel_P, 00122 typename Radio_P, 00123 typename Clock_P, 00124 typename Debug_P, 00125 typename NeighborhoodDiscovery_P, 00126 uint16_t MAX_NODES> 00127 LtsSynchronization<OsModel_P, Radio_P, Clock_P, Debug_P, NeighborhoodDiscovery_P, MAX_NODES>:: 00128 LtsSynchronization() 00129 {}; 00130 // ----------------------------------------------------------------------- 00131 template<typename OsModel_P, 00132 typename Radio_P, 00133 typename Clock_P, 00134 typename Debug_P, 00135 typename NeighborhoodDiscovery_P, 00136 uint16_t MAX_NODES> 00137 LtsSynchronization<OsModel_P, Radio_P, Clock_P, Debug_P, NeighborhoodDiscovery_P, MAX_NODES>:: 00138 ~LtsSynchronization() 00139 { 00140 #ifdef DEBUG_LTS_SYNCHRONIZATION 00141 debug().debug( "LtsSynchronization Destroyed\n" ); 00142 #endif 00143 }; 00144 // ----------------------------------------------------------------------- 00145 template<typename OsModel_P, 00146 typename Radio_P, 00147 typename Clock_P, 00148 typename Debug_P, 00149 typename NeighborhoodDiscovery_P, 00150 uint16_t MAX_NODES> 00151 void 00152 LtsSynchronization<OsModel_P, Radio_P, Clock_P, Debug_P, NeighborhoodDiscovery_P, MAX_NODES>:: 00153 init ( Radio& radio, Clock& clock, Debug& debug, NeighborhoodDiscovery& neighborhood_discovery ) 00154 { 00155 radio_ = &radio; 00156 clock_ = &clock; 00157 debug_ = &debug; 00158 neighborhood_discovery_ = &neighborhood_discovery; 00159 #ifdef DEBUG_LTS_SYNCHRONIZATION 00160 debug().debug( "LtsSynchronization Boots for %i\n", radio().id() ); 00161 #endif 00162 radio().enable_radio(); 00163 radio().template reg_recv_callback<self_type, &self_type::receive>( this ); 00164 00165 neighborhood_discovery_.set_root( root ); 00166 neighborhood_discovery().template reg_finish_callback<self_type, &self_type::start_synchronization>( this ); 00167 neighborhood_discovery_.reinit(); 00168 } 00169 // ----------------------------------------------------------------------- 00170 template<typename OsModel_P, 00171 typename Radio_P, 00172 typename Clock_P, 00173 typename Debug_P, 00174 typename NeighborhoodDiscovery_P, 00175 uint16_t MAX_NODES> 00176 void 00177 LtsSynchronization<OsModel_P, Radio_P, Clock_P, Debug_P, NeighborhoodDiscovery_P, MAX_NODES>:: 00178 receive( node_id_t from, size_t len, block_data_t *data ) 00179 { 00180 uint8_t msg_id = *data; 00181 #ifdef DEBUG_LTS_SYNCHRONIZATION 00182 debug().debug( "%i: Received %d message from %i\n", radio().id(), msg_id, from ); 00183 #endif 00184 if ( msg_id == LtsMsgIdSynchronizationPulse ) 00185 { 00186 synchronizationMessage.set_t2( clock().time() ); 00187 SynchronizationMessage *msg = ( SynchronizationMessage * )data; 00188 synchronizationMessage.set_msg_id( LtsMsgIdAcknowledgement ); 00189 synchronizationMessage.set_t1( msg->t1() ); 00190 synchronizationMessage.set_t3( clock().time() ); 00191 radio().send( from, 1 + 3*TIME_SIZE, (uint8_t*)&synchronizationMessage ); 00192 } 00193 else if ( msg_id == LtsMsgIdAcknowledgement ) 00194 { 00195 Time t4 = clock().time(); 00196 SynchronizationMessage *msg = (SynchronizationMessage *)data; 00197 Time offset = ( msg->t2() + msg->t3() - msg->t1() - t4 )/2; 00198 synchronizationMessage.set_msg_id( LtsMsgIdOffset ); 00199 synchronizationMessage.set_t1( offset ); 00200 radio().send( from, 1 + TIME_SIZE, (uint8_t*)&synchronizationMessage ); 00201 } 00202 else if ( msg_id == LtsMsgIdOffset ) { 00203 SynchronizationMessage *msg = (SynchronizationMessage *)data; 00204 clock().set_time( clock().time() + msg->t1() ); 00205 #ifdef DEBUG_LTS_SYNCHRONIZATION_SHAWN 00206 debug().debug( "%i: My new time is %f\n", radio().id(), clock().time() + msg->t1() ); 00207 #endif 00208 notify_listeners(); 00209 start_synchronization(); 00210 } 00211 } 00212 // ----------------------------------------------------------------------- 00213 template<typename OsModel_P, 00214 typename Radio_P, 00215 typename Clock_P, 00216 typename Debug_P, 00217 typename NeighborhoodDiscovery_P, 00218 uint16_t MAX_NODES> 00219 void 00220 LtsSynchronization<OsModel_P, Radio_P, Clock_P, Debug_P, NeighborhoodDiscovery_P, MAX_NODES>:: 00221 start_synchronization( ) 00222 { 00223 // Send the synchronization pulse to all children 00224 synchronizationMessage.set_msg_id( LtsMsgIdSynchronizationPulse ); 00225 for ( int i = 0; i < (int)neighbors_.children_.size(); ++i ) { 00226 #ifdef DEBUG_LTS_SYNCHRONIZATION 00227 debug().debug( "%i: Sending synch_pulse to %i\n", radio().id(), neighbors_.children_[i] ); 00228 #endif 00229 synchronizationMessage.set_t1( clock().time() ); 00230 radio().send( neighbors_.children_[i], 1 + TIME_SIZE, (uint8_t*)&synchronizationMessage ); 00231 } 00232 } 00233 } 00234 #endif