Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
message_bus.h
00001 /****************************************************************************** 00002 The MIT License(MIT) 00003 00004 Embedded Template Library. 00005 https://github.com/ETLCPP/etl 00006 https://www.etlcpp.com 00007 00008 Copyright(c) 2017 jwellbelove 00009 00010 Permission is hereby granted, free of charge, to any person obtaining a copy 00011 of this software and associated documentation files(the "Software"), to deal 00012 in the Software without restriction, including without limitation the rights 00013 to use, copy, modify, merge, publish, distribute, sublicense, and / or sell 00014 copies of the Software, and to permit persons to whom the Software is 00015 furnished to do so, subject to the following conditions : 00016 00017 The above copyright notice and this permission notice shall be included in all 00018 copies or substantial portions of the Software. 00019 00020 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00021 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00022 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE 00023 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00024 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00025 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 00026 SOFTWARE. 00027 ******************************************************************************/ 00028 00029 #ifndef __ETL_MESSAGE_BUS_ 00030 #define __ETL_MESSAGE_BUS_ 00031 00032 #include <stdint.h> 00033 #include <algorithm> 00034 00035 #include "platform.h " 00036 #include "algorithm.h " 00037 #include "vector.h " 00038 #include "nullptr.h " 00039 #include "error_handler.h " 00040 #include "exception.h " 00041 #include "message_types.h" 00042 #include "message.h" 00043 #include "message_router.h" 00044 00045 #undef ETL_FILE 00046 #define ETL_FILE "39" 00047 00048 namespace etl 00049 { 00050 //*************************************************************************** 00051 /// Base exception class for message bus 00052 //*************************************************************************** 00053 class message_bus_exception : public etl::exception 00054 { 00055 public: 00056 00057 message_bus_exception(string_type reason_, string_type file_name_, numeric_type line_number_) 00058 : etl::exception(reason_, file_name_, line_number_) 00059 { 00060 } 00061 }; 00062 00063 //*************************************************************************** 00064 /// Too many subscribers. 00065 //*************************************************************************** 00066 class message_bus_too_many_subscribers : public etl::message_bus_exception 00067 { 00068 public: 00069 00070 message_bus_too_many_subscribers(string_type file_name_, numeric_type line_number_) 00071 : message_bus_exception(ETL_ERROR_TEXT("message bus:too many subscribers", ETL_FILE"A"), file_name_, line_number_) 00072 { 00073 } 00074 }; 00075 00076 //*************************************************************************** 00077 /// Interface for message bus 00078 //*************************************************************************** 00079 class imessage_bus : public etl::imessage_router 00080 { 00081 private: 00082 00083 typedef etl::ivector<etl::imessage_router*> router_list_t ; 00084 00085 public: 00086 00087 using etl::imessage_router::receive; 00088 00089 //******************************************* 00090 /// Subscribe to the bus. 00091 //******************************************* 00092 bool subscribe(etl::imessage_router& router) 00093 { 00094 bool ok = true; 00095 00096 // There's no point actually adding null routers. 00097 if (!router.is_null_router()) 00098 { 00099 ok = !router_list.full(); 00100 00101 ETL_ASSERT(ok, ETL_ERROR(etl::message_bus_too_many_subscribers)); 00102 00103 if (ok) 00104 { 00105 if (router.is_bus()) 00106 { 00107 // Message busses get added to the end. 00108 router_list.push_back(&router); 00109 } 00110 else 00111 { 00112 // Routers get added in id order. 00113 router_list_t::iterator irouter = std::upper_bound(router_list.begin(), 00114 router_list.end(), 00115 router.get_message_router_id(), 00116 compare_router_id()); 00117 00118 router_list.insert(irouter, &router); 00119 } 00120 } 00121 } 00122 00123 return ok; 00124 } 00125 00126 //******************************************* 00127 /// Unsubscribe from the bus. 00128 //******************************************* 00129 void unsubscribe(etl::message_router_id_t id) 00130 { 00131 if (id == etl::imessage_bus::ALL_MESSAGE_ROUTERS) 00132 { 00133 clear(); 00134 } 00135 else 00136 { 00137 std::pair<router_list_t::iterator, router_list_t::iterator> range = std::equal_range(router_list.begin(), 00138 router_list.end(), 00139 id, 00140 compare_router_id()); 00141 00142 router_list.erase(range.first, range.second); 00143 } 00144 } 00145 00146 //******************************************* 00147 void unsubscribe(etl::imessage_router& router) 00148 { 00149 router_list_t::iterator irouter = std::find(router_list.begin(), 00150 router_list.end(), 00151 &router); 00152 00153 if (irouter != router_list.end()) 00154 { 00155 router_list.erase(irouter); 00156 } 00157 } 00158 00159 //******************************************* 00160 void receive(const etl::imessage& message) 00161 { 00162 etl::null_message_router nmr; 00163 receive(nmr, etl::imessage_router::ALL_MESSAGE_ROUTERS, message); 00164 } 00165 00166 //******************************************* 00167 void receive(etl::message_router_id_t destination_router_id, 00168 const etl::imessage& message) 00169 { 00170 etl::null_message_router nmr; 00171 receive(nmr, destination_router_id, message); 00172 } 00173 00174 //******************************************* 00175 void receive(etl::imessage_router& source, 00176 const etl::imessage& message) 00177 { 00178 receive(source, etl::imessage_router::ALL_MESSAGE_ROUTERS, message); 00179 } 00180 00181 //******************************************* 00182 void receive(etl::imessage_router& source, 00183 etl::message_router_id_t destination_router_id, 00184 const etl::imessage& message) 00185 { 00186 switch (destination_router_id) 00187 { 00188 //***************************** 00189 // Null message router. These routers can never be subscribed. 00190 case etl::imessage_router::NULL_MESSAGE_ROUTER: 00191 { 00192 break; 00193 } 00194 00195 //***************************** 00196 // Broadcast to all routers. 00197 case etl::imessage_router::ALL_MESSAGE_ROUTERS: 00198 { 00199 router_list_t::iterator irouter = router_list.begin(); 00200 00201 // Broadcast to everyone. 00202 while (irouter != router_list.end()) 00203 { 00204 etl::imessage_router& router = **irouter; 00205 00206 if (router.is_bus()) 00207 { 00208 // The router is actually a bus. 00209 etl::imessage_bus& bus = static_cast<etl::imessage_bus&>(router); 00210 00211 // So pass it on. 00212 bus.receive(source, destination_router_id, message); 00213 } 00214 else if (router.accepts(message.message_id)) 00215 { 00216 router.receive(source, message); 00217 } 00218 00219 ++irouter; 00220 } 00221 00222 break; 00223 } 00224 00225 //***************************** 00226 // Must be an addressed message. 00227 default: 00228 { 00229 router_list_t::iterator irouter = router_list.begin(); 00230 00231 // Find routers with the id. 00232 std::pair<router_list_t::iterator, router_list_t::iterator> range = std::equal_range(router_list.begin(), 00233 router_list.end(), 00234 destination_router_id, 00235 compare_router_id()); 00236 00237 // Call all of them. 00238 while (range.first != range.second) 00239 { 00240 if ((*(range.first))->accepts(message.message_id)) 00241 { 00242 (*(range.first))->receive(source, message); 00243 } 00244 00245 ++range.first; 00246 } 00247 00248 // Do any message buses. 00249 // These are always at the end of the list. 00250 irouter = std::lower_bound(router_list.begin(), 00251 router_list.end(), 00252 etl::imessage_bus::MESSAGE_BUS, 00253 compare_router_id()); 00254 00255 while (irouter != router_list.end()) 00256 { 00257 // The router is actually a bus. 00258 etl::imessage_bus& bus = static_cast<etl::imessage_bus&>(**irouter); 00259 00260 // So pass it on. 00261 bus.receive(source, destination_router_id, message); 00262 00263 ++irouter; 00264 } 00265 00266 break; 00267 } 00268 } 00269 } 00270 00271 using imessage_router::accepts; 00272 00273 //******************************************* 00274 /// Does this message bus accept the message id? 00275 /// Yes!, it accepts everything! 00276 //******************************************* 00277 bool accepts(etl::message_id_t) const 00278 { 00279 return true; 00280 } 00281 00282 //******************************************* 00283 size_t size() const 00284 { 00285 return router_list.size(); 00286 } 00287 00288 //******************************************* 00289 void clear() 00290 { 00291 return router_list.clear(); 00292 } 00293 00294 protected: 00295 00296 //******************************************* 00297 /// Constructor. 00298 //******************************************* 00299 imessage_bus(router_list_t & list) 00300 : imessage_router(etl::imessage_router::MESSAGE_BUS), 00301 router_list(list) 00302 { 00303 } 00304 00305 private: 00306 00307 //******************************************* 00308 // How to compare routers to router ids. 00309 //******************************************* 00310 struct compare_router_id 00311 { 00312 bool operator()(const etl::imessage_router* prouter, etl::message_router_id_t id) const 00313 { 00314 return prouter->get_message_router_id() < id; 00315 } 00316 00317 bool operator()(etl::message_router_id_t id, const etl::imessage_router* prouter) const 00318 { 00319 return id < prouter->get_message_router_id(); 00320 } 00321 }; 00322 00323 router_list_t& router_list; 00324 }; 00325 00326 //*************************************************************************** 00327 /// The message bus 00328 //*************************************************************************** 00329 template <uint_least8_t MAX_ROUTERS_> 00330 class message_bus : public etl::imessage_bus 00331 { 00332 public: 00333 00334 //******************************************* 00335 /// Constructor. 00336 //******************************************* 00337 message_bus() 00338 : imessage_bus(router_list) 00339 { 00340 } 00341 00342 private: 00343 00344 etl::vector<etl::imessage_router*, MAX_ROUTERS_> router_list; 00345 }; 00346 00347 //*************************************************************************** 00348 /// Send a message to a bus. 00349 //*************************************************************************** 00350 inline static void send_message(etl::imessage_bus& bus, 00351 const etl::imessage& message) 00352 { 00353 bus.receive(message); 00354 } 00355 00356 //*************************************************************************** 00357 /// Send a message to a bus. 00358 //*************************************************************************** 00359 inline static void send_message(etl::imessage_bus& bus, 00360 etl::message_router_id_t id, 00361 const etl::imessage& message) 00362 { 00363 bus.receive(id, message); 00364 } 00365 00366 //*************************************************************************** 00367 /// Send a message to a bus. 00368 //*************************************************************************** 00369 inline static void send_message(etl::imessage_router& source, 00370 etl::imessage_bus& bus, 00371 const etl::imessage& message) 00372 { 00373 bus.receive(source, message); 00374 } 00375 00376 //*************************************************************************** 00377 /// Send a message to a bus. 00378 //*************************************************************************** 00379 inline static void send_message(etl::imessage_router& source, 00380 etl::imessage_bus& bus, 00381 etl::message_router_id_t id, 00382 const etl::imessage& message) 00383 { 00384 bus.receive(source, id, message); 00385 } 00386 } 00387 00388 #undef ETL_FILE 00389 00390 #endif 00391
Generated on Tue Jul 12 2022 14:05:42 by
