Tengo una larga lista de condiciones de cadena. Para baja latencia y legibilidad del código, prefiero usar switch que "else if". Gracias a los comentarios, edité esta pregunta e implementé el cambio asignando una cadena a invocable:
#include <unordered_map> #include <iostream> #include <functional> #include <thread> struct Message{ Message(const std::string field_name, const std::string data) : m_FieldName(field_name), m_Data(data) {} const std::string m_FieldName; const std::string m_Data; }; class Handler{ static const std::unordered_map<std::string, std::function<void(const Message &)>> m_FieldNameCallback; public: bool operator()(Message message){ bool res = true; auto it = m_FieldNameCallback.find(message.m_FieldName); if(it != m_FieldNameCallback.cend()){ it->second(message); } else{ std::cout << "Invalid message with field name: " << message.m_FieldName <<"\n"; res = false; } return res; } }; const std::unordered_map<std::string, std::function<void(const Message &)>> Handler::m_FieldNameCallback = { {"BusinessAction", [](const Message & message){std::cout<< 5 << ": " << message.m_Data << "\n";}}, {"BusinessClass", [](const Message & message){std::cout<< 6 << ": " << message.m_Data << "\n";}}, //... {"PriceVariation", [](const Message & message){std::cout<< 695 << ": " << message.m_Data << "\n";}}, {"PairedVolume", [](const Message & message){std::cout<< 698 << ": " << message.m_Data << "\n";}} }; int main(){ Handler h1; std::thread t1(h1, Message("BusinessAction", "&&&##@@@")); std::thread t2(h1, Message("BusinessClass", "&##@")); std::thread t3(h1, Message("Business", "&##@")); t1.join(); t2.join(); t3.join(); }¿Es seguro el subproceso del controlador? usando C ++ moderno, ¿hay algún método más idiomático para cambiar la cadena?
Definitivamente hiciste un buen progreso. Haga que el mapa sea un miembro no estático de la función de controlador estática. Ahora creo que hay una mezcla extraña. Aquí hay algunas cosas que haría un poco diferentes, si tiene preguntas, hágamelo saber.
#include <unordered_map> #include <iostream> #include <functional> #include <future> struct Message { Message(const std::string field_name, const std::string data) : m_FieldName(field_name), m_Data(data) {} const std::string m_FieldName; const std::string m_Data; }; //--------------------------------------------------------------------------------------------------------------------- class Handler final // small tweak, no inheritance support (eg virtual methods/destructor) { /*static*/ const std::unordered_map<std::string, std::function<void(const Message&)>> m_FieldNameCallback; std::mutex m_output_mtx; public: Handler() : m_FieldNameCallback { {"BusinessAction", [this](const Message& message) {show_message(5,message); }}, {"BusinessClass", [this](const Message& message) {show_message(6,message); }}, //... {"PriceVariation", [this](const Message& message) {show_message(695,message); }}, {"PairedVolume", [this](const Message& message) {show_message(698,message); }} } { } bool operator()(const Message& message) // pass by const ref, message should not change and ref will avoid copy { // I prefer exception based error handling, so an example of that here. // also allows us to use at() instead of find try { // no lock needed since map is readonly auto callback = m_FieldNameCallback.at(message.m_FieldName); callback(message); return true; } catch (const std::out_of_range&) { show_invalid_message(message); return false; } } private: void show_invalid_message(const Message& message) { std::unique_lock<std::mutex> lock(m_output_mtx); std::cout << "Invalid message with field name: " << message.m_FieldName << "\n"; } void show_message(unsigned int number, const Message& message) { std::unique_lock<std::mutex> lock(m_output_mtx); std::cout << number << ": " << message.m_Data << "\n"; } }; int main() { Handler handler; // async is a higher level abstraction then thread // it also allows you to get values calculated on other thread wiht future.get() // also any uncaught exceptions will be rethrown by get (allowing you to pass errors between threads) auto ft1 = std::async(std::launch::async, [&handler] { handler(Message{ "BusinessAction", "&&&##@@@" }); }); auto ft2 = std::async(std::launch::async, [&handler] { handler(Message{ "BusinessClass", "&##@" }); }); auto ft3 = std::async(std::launch::async, [&handler] { handler(Message{ "Business", "&##@" }); }); ft1.get(); ft2.get(); ft3.get(); return 0; }