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



WtShapeGroupWidget is a Wt class used for notifying all clients from different IP addresses.
Technical facts
./CppWtTimedServerPusher/CppWtTimedServerPusher.pri
INCLUDEPATH += \ ../../Classes/CppWtTimedServerPusher SOURCES += \ ../../Classes/CppWtTimedServerPusher/wttimedserverpusher.cpp \ ../../Classes/CppWtTimedServerPusher/wttimedserverpusherclient.cpp HEADERS += \ ../../Classes/CppWtTimedServerPusher/wttimedserverpusher.h \ ../../Classes/CppWtTimedServerPusher/wttimedserverpusherclient.h OTHER_FILES += \ ../../Classes/CppWtTimedServerPusher/Licence.txt
./CppWtTimedServerPusher/wttimedserverpusher.h
//--------------------------------------------------------------------------- /* WtTimedServerPusher, server to broadcast to all its WtTimedServerPusherClients Copyright 2011-2015 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/CppWtTimedServerPusher.htm //--------------------------------------------------------------------------- #ifndef WTTIMEDSERVERPUSHER_H #define WTTIMEDSERVERPUSHER_H #include <regex> #include <thread> #include <vector> #include <boost/any.hpp> #include <boost/function.hpp> #include <boost/scoped_ptr.hpp> namespace ribi { struct WtTimedServerPusherClient; ///A Server that broadcasts its messages struct WtTimedServerPusher { ///Let a WtTimedServerPusherClient have its supplied function called by WtTimedServerPusher::Run void Connect(WtTimedServerPusherClient * const client, const boost::function<void()>& function); ///Stop a WtTimedServerPusherClient have its supplied function called by TimePollServer::Run void Disconnect(const WtTimedServerPusherClient* const client); public: ///Obtain the only instace to WtTimedServerPusher static WtTimedServerPusher * GetInstance(); ///Get the version of this class static std::string GetVersion(); ///Get the version history of this class static std::vector<std::string> GetVersionHistory(); ///\brief ///Set the time (in milliseconds) WtTimedServerPusherClient::UpdatePage is to be called /// ///Use a time of zero to only let WtTimedServerPusherClient::UpdatePage be ///called upon Post void SetTime(const int time); private: //Connection is a POD struct Connection { Connection( const std::string& session_id, WtTimedServerPusherClient * client, const boost::function<void()>& function) : m_session_id(session_id),m_client(client),m_function(function) { } Connection(const Connection&) = delete; Connection& operator=(const Connection&) = delete; const std::string m_session_id; WtTimedServerPusherClient * const m_client; const boost::function<void()> m_function; }; ///WtTimedServerPusher constructor, which is private, because WtTimedServerPusher follows ///the Singleton design pattern WtTimedServerPusher(); ///WtTimedServerPusher destructor ~WtTimedServerPusher(); ///Only let a smart pointer (that is, m_instance) delete WtTimedServerPusher friend void boost::checked_delete<>(WtTimedServerPusher*); ///All connections to the WtTimedServerPusherClients std::vector<boost::shared_ptr<Connection> > m_connections; ///The WtTimedServerPusher its only instance static boost::scoped_ptr<WtTimedServerPusher> 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 WtTimedServerPusher::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(); }; } //~namespace ribi #endif // WTTIMEDSERVERPUSHER_H
./CppWtTimedServerPusher/wttimedserverpusher.cpp
//--------------------------------------------------------------------------- /* WtTimedServerPusher, server to broadcast to all its WtTimedServerPusherClients Copyright 2011-2015 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/CppWtTimedServerPusher.htm //--------------------------------------------------------------------------- #include <algorithm> #include <chrono> #include <numeric> #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Weffc++" #pragma GCC diagnostic ignored "-Wunused-local-typedefs" #pragma GCC diagnostic ignored "-Wunused-but-set-variable" #include <boost/bind.hpp> #include <Wt/WApplication> #include <Wt/WServer> #include "wttimedserverpusher.h" #pragma GCC diagnostic pop boost::scoped_ptr<ribi::WtTimedServerPusher> ribi::WtTimedServerPusher::m_instance; ribi::WtTimedServerPusher::WtTimedServerPusher() : m_connections{}, m_data{}, m_mutex{}, m_running(true), m_thread(boost::bind(&ribi::WtTimedServerPusher::Run, this)), m_time(1000) { } ribi::WtTimedServerPusher::~WtTimedServerPusher() { m_running = false; m_thread.join(); } void ribi::WtTimedServerPusher::Connect( WtTimedServerPusherClient * const client, const boost::function<void()>& function) { std::lock_guard<std::mutex> lock(m_mutex); const boost::shared_ptr<Connection> connection { new Connection( Wt::WApplication::instance()->sessionId(), client, function ) }; m_connections.push_back(connection); } void ribi::WtTimedServerPusher::Disconnect(const WtTimedServerPusherClient* const client) { std::lock_guard<std::mutex> lock(m_mutex); m_connections.erase( std::remove_if(m_connections.begin(),m_connections.end(), [client](const boost::shared_ptr<Connection> c) { return c->m_client == client; } )); } ribi::WtTimedServerPusher * ribi::WtTimedServerPusher::GetInstance() { if (!m_instance) m_instance.reset(new WtTimedServerPusher); return m_instance.get(); } std::string ribi::WtTimedServerPusher::GetVersion() { return "1.0"; } std::vector<std::string> ribi::WtTimedServerPusher::GetVersionHistory() { return { "2011-08-05: version 1.0: initial version" }; } void ribi::WtTimedServerPusher::Run() { while (m_running) { std::this_thread::sleep_for(std::chrono::milliseconds(m_time)); { std::lock_guard<std::mutex> lock(m_mutex); std::for_each(m_connections.begin(),m_connections.end(), [](const boost::shared_ptr<Connection> i) { Wt::WServer::instance()->post(i->m_session_id, i->m_function); }); } } } void ribi::WtTimedServerPusher::SetTime(const int time) { std::lock_guard<std::mutex> lock(m_mutex); if (m_running) { if (time <= 0) { //stop WtTimedServerPusher, although thread needs to finish first m_time = 0; m_running = false; } else { //Change time, although thread needs to finish first m_time = time; } } else { if (time <= 0) { //stop stopped WtTimedServerPusher m_time = 0; } else { //Start stopped WtTimedServerPusher m_running = true; m_time = time; m_thread = std::thread(boost::bind(&ribi::WtTimedServerPusher::Run, this)); } } }
./CppWtTimedServerPusher/wttimedserverpusherclient.h
//--------------------------------------------------------------------------- /* WtTimedServerPusherClient, client of WtTimedServerPusher Copyright 2011-2015 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/CppWtTimedServerPusherClient.htm //--------------------------------------------------------------------------- #ifndef WTTIMEDSERVERPUSHERCLIENT_H #define WTTIMEDSERVERPUSHERCLIENT_H #include <string> #include <vector> namespace ribi { ///WtTimedServerPusherClient is a client responding to WtTimedServerPusher ///and to be used as a base class struct WtTimedServerPusherClient { virtual ~WtTimedServerPusherClient(); ///Get the version of this class static std::string GetVersion(); ///Get the version history of this class static std::vector<std::string> GetVersionHistory(); ///UpdatePage is called when the WtTimedServerPusher triggers an update by timer virtual void OnTimedServerPush() = 0; protected: ///WtTimedServerPusherClient constructor is protected ///because it is to be used as a base class WtTimedServerPusherClient(); private: ///Respond to the server void OnServer(); }; } //~namespace ribi #endif // WTTIMEDSERVERPUSHERCLIENT_H
./CppWtTimedServerPusher/wttimedserverpusherclient.cpp
//--------------------------------------------------------------------------- /* WtTimedServerPusherClient, client of WtTimedServerPusher Copyright 2011-2015 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/CppWtTimedServerPusherClient.htm //--------------------------------------------------------------------------- #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 "wttimedserverpusher.h" #include "wttimedserverpusherclient.h" #pragma GCC diagnostic pop ribi::WtTimedServerPusherClient::WtTimedServerPusherClient() { Wt::WApplication::instance()->enableUpdates(true); ribi::WtTimedServerPusher::GetInstance()->Connect( this,boost::bind(&ribi::WtTimedServerPusherClient::OnServer,this)); //Never call virtual functions during construction or destruction //Scott Meyers, Effective C++, item 9 //OnServer(); } ribi::WtTimedServerPusherClient::~WtTimedServerPusherClient() { Wt::WApplication::instance()->enableUpdates(false); ribi::WtTimedServerPusher::GetInstance()->Disconnect(this); } std::string ribi::WtTimedServerPusherClient::GetVersion() { return "1.0"; } std::vector<std::string> ribi::WtTimedServerPusherClient::GetVersionHistory() { return { "2011-08-05: version 1.0: initial version" }; } void ribi::WtTimedServerPusherClient::OnServer() { OnTimedServerPush(); Wt::WApplication::instance()->triggerUpdate(); }