Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) WtBroadcastServer

 

WtQt CreatorLubuntu

 

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 (C) 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 (C) 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 (C) 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();
}
//---------------------------------------------------------------------------

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml