(C++) WtBroadcastServer
January 25, 2018 · View on GitHub
(C++) WtBroadcastServer



WtBroadcastServer has been abandoned, because it served two tasks. It is split up into and replaced by WtServerPusher and WtTimedServerPusher.
WtBroadcastServerClient has been abandoned, because it served two tasks. It is split up into and replaced by WtServerPusherClient and WtTimedServerPusherClient.
Technical facts
./CppWtBroadcastServer/CppWtBroadcastServer.pri
INCLUDEPATH += \ ../../Classes/CppWtBroadcastServer SOURCES += \ ../../Classes/CppWtBroadcastServer/wtbroadcastserver.cpp HEADERS += \ ../../Classes/CppWtBroadcastServer/wtbroadcastserver.h OTHER_FILES += \ ../../Classes/CppWtBroadcastServer/Licence.txt
./CppWtBroadcastServer/wtbroadcastserver.h
//--------------------------------------------------------------------------- /* WtBroadcastServer, server to broadcast to all its WtBroadcastServerClients Copyright 2011-2014 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppWtBroadcastServer.htm //--------------------------------------------------------------------------- #ifndef WTBROADCASTSERVER_H #define WTBROADCASTSERVER_H #include <regex> #include <thread> #include <vector> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <boost/any.hpp> #include <boost/function.hpp> #include <boost/scoped_ptr.hpp> #pragma GCC diagnostic pop struct WtBroadcastServerClient; ///A Server that broadcasts its messages struct WtBroadcastServer { ///Let a WtBroadcastServerClient have its supplied function called by WtBroadcastServer::Run void Connect(WtBroadcastServerClient * const client, const boost::function<void()>& function); ///Stop a WtBroadcastServerClient have its supplied function called by TimePollServer::Run void Disconnect(const WtBroadcastServerClient* const client); //private: ///\brief ///Get a _copy_ of the data by reference /// ///GetData is implemented by references, so that obtaining the data ///can also be done thread-safe, that is, locked by a mutex void GetData(boost::any& data) const; public: ///Obtain the only instace to WtBroadcastServer static WtBroadcastServer * GetInstance(); ///Get the version of this class static const std::string GetVersion(); ///Get the version history of this class static const std::vector<std::string> GetVersionHistory(); ///Post calls all WtBroadcastServerClients' supplied functions void Post(); //private: ///Set the data void SetData(const boost::any& data); public: ///\brief ///Set the time (in milliseconds) WtBroadcastServerClient::UpdatePage is to be called /// ///Use a time of zero to only let WtBroadcastServerClient::UpdatePage be ///called upon Post void SetTime(const int time); private: //Connection is a POD struct Connection { Connection( const std::string& session_id, WtBroadcastServerClient * client, const boost::function<void()>& function) : m_session_id(session_id),m_client(client),m_function(function) { } std::string m_session_id; WtBroadcastServerClient * m_client; boost::function<void()> m_function; }; ///WtBroadcastServer constructor, which is private, because WtBroadcastServer follows ///the Singleton design pattern WtBroadcastServer(); ///WtBroadcastServer destructor ~WtBroadcastServer(); ///Only let a smart pointer (that is, m_instance) delete WtBroadcastServer friend void boost::checked_delete<>(WtBroadcastServer*); ///All connections to the WtBroadcastServerClients std::vector<Connection> m_connections; ///The WtBroadcastServer its only instance static boost::scoped_ptr<WtBroadcastServer> m_instance; ///The data, can be anything boost::any m_data; ///A mutex mutable std::mutex m_mutex; ///If the Server is running bool m_running; ///The thread for WtBroadcastServer::Run std::thread m_thread; ///The number of milliseconds before Run triggers Post int m_time; ///The member function that is called every 100 msecs void Run(); }; #endif // WTBROADCASTSERVER_H
./CppWtBroadcastServer/wtbroadcastserver.cpp
//--------------------------------------------------------------------------- /* WtBroadcastServer, server to broadcast to all its WtBroadcastServerClients Copyright 2011-2014 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppWtBroadcastServer.htm //--------------------------------------------------------------------------- #include "wtbroadcastserver.h" #include <algorithm> #include <chrono> #include <numeric> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-but-set-parameter" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #include <boost/bind.hpp> #include <Wt/WApplication> #include <Wt/WServer> #pragma GCC diagnostic pop boost::scoped_ptr<WtBroadcastServer> WtBroadcastServer::m_instance; WtBroadcastServer::WtBroadcastServer() : m_running(true), m_thread(boost::bind(&WtBroadcastServer::Run, this)), m_time(1000) { } WtBroadcastServer::~WtBroadcastServer() { m_running = false; m_thread.join(); } void WtBroadcastServer::Connect( WtBroadcastServerClient * const client, const boost::function<void()>& function) { std::lock_guard<std::mutex> lock(m_mutex); m_connections.push_back( Connection( Wt::WApplication::instance()->sessionId(), client, function)); } void WtBroadcastServer::Disconnect(const WtBroadcastServerClient* const client) { std::lock_guard<std::mutex> lock(m_mutex); m_connections.erase( std::remove_if(m_connections.begin(),m_connections.end(), [client](const Connection& c) { return c.m_client == client; } )); } void WtBroadcastServer::GetData(boost::any& data) const { //Let this thread sleep, to give the other thread a chance std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::lock_guard<std::mutex> lock(m_mutex); data = m_data; } WtBroadcastServer * WtBroadcastServer::GetInstance() { if (!m_instance) m_instance.reset(new WtBroadcastServer); return m_instance.get(); } const std::string WtBroadcastServer::GetVersion() { return "3.0"; } const std::vector<std::string> WtBroadcastServer::GetVersionHistory() { std::vector<std::string> v; v.push_back("2011-07-27: version 1.0: initial version"); v.push_back("2011-07-29: version 2.0: added Post member function"); v.push_back("2011-07-29: version 2.1: fixed bug in timed updates"); v.push_back("2011-08-01: version 3.0: made reading data thread-safe"); return v; } void WtBroadcastServer::Post() { ///Let this thread sleep, to give the other thread a chance //std::this_thread::sleep_for(std::chrono::milliseconds(10)); std::lock_guard<std::mutex> lock(m_mutex); std::for_each(m_connections.begin(),m_connections.end(), [](const Connection& i) { Wt::WServer::instance()->post(i.m_session_id, i.m_function); }); } void WtBroadcastServer::Run() { while (m_running) { std::this_thread::sleep_for(std::chrono::milliseconds(m_time)); { std::lock_guard<std::mutex> lock(m_mutex); //Do not call Post here! std::for_each(m_connections.begin(),m_connections.end(), [](const Connection& i) { Wt::WServer::instance()->post(i.m_session_id, i.m_function); }); } } } void WtBroadcastServer::SetData(const boost::any& data) { ///Let this thread sleep, to give the other thread a chance //std::this_thread::sleep_for(std::chrono::milliseconds(1)); std::lock_guard<std::mutex> lock(m_mutex); m_data = data; //Notify the WtBroadcastServerClients //Do not call Post here! std::for_each(m_connections.begin(),m_connections.end(), [](const Connection& i) { Wt::WServer::instance()->post(i.m_session_id, i.m_function); }); } void WtBroadcastServer::SetTime(const int time) { std::lock_guard<std::mutex> lock(m_mutex); m_running = time > 0; m_time = time; }
./CppWtBroadcastServer/wtbroadcastserverclient.h
//--------------------------------------------------------------------------- #ifndef WTBROADCASTSERVERCLIENT_H #define WTBROADCASTSERVERCLIENT_H //--------------------------------------------------------------------------- #include <string> #include <vector> //--------------------------------------------------------------------------- ///WtBroadcastServerClient is a client responding to WtBroadcastServer ///and to be used as a base class struct WtBroadcastServerClient { virtual ~WtBroadcastServerClient(); ///Get the version of this class static const std::string GetVersion(); ///Get the version history of this class static const std::vector<std::string> GetVersionHistory(); ///UpdatePage is called when the WtBroadcastServer triggers an update by timer virtual void UpdatePage() = 0; protected: ///WtBroadcastServerClient constructor is protected ///because it is to be used as a base class WtBroadcastServerClient(); private: ///Respond to the server void OnServer(); }; //--------------------------------------------------------------------------- #endif // WTBROADCASTSERVERCLIENT_H
./CppWtBroadcastServer/wtbroadcastserverclient.cpp
//--------------------------------------------------------------------------- /* WtBroadcastServerClient, client of WtBroadcastServer Copyright 2011 Richel Bilderbeek This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ //--------------------------------------------------------------------------- //From http://www.richelbilderbeek.nl/CppWtBroadcastServerClient.htm //--------------------------------------------------------------------------- #include <boost/bind.hpp> //--------------------------------------------------------------------------- #include <Wt/WApplication> //--------------------------------------------------------------------------- #include "wtbroadcastserver.h" #include "wtbroadcastserverclient.h" //--------------------------------------------------------------------------- WtBroadcastServerClient::WtBroadcastServerClient() { Wt::WApplication::instance()->enableUpdates(true); WtBroadcastServer::GetInstance()->Connect( this,boost::bind(&WtBroadcastServerClient::OnServer,this)); //Never call virtual functions during construction or destruction //Scott Meyers, Effective C++, item 9 //OnServer(); } //--------------------------------------------------------------------------- WtBroadcastServerClient::~WtBroadcastServerClient() { Wt::WApplication::instance()->enableUpdates(false); WtBroadcastServer::GetInstance()->Disconnect(this); } //--------------------------------------------------------------------------- const std::string WtBroadcastServerClient::GetVersion() { return "1.0"; } //--------------------------------------------------------------------------- const std::vector<std::string> WtBroadcastServerClient::GetVersionHistory() { std::vector<std::string> v; v.push_back("2011-07-27: version 1.0: initial version"); return v; } //--------------------------------------------------------------------------- void WtBroadcastServerClient::OnServer() { UpdatePage(); Wt::WApplication::instance()->triggerUpdate(); } //---------------------------------------------------------------------------