Go back to Richel Bilderbeek's homepage.

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

 

 

 

 

 

(C++) WtServerPusher

 

WtQt CreatorLubuntu

 

WtShapeGroupWidget is a Wt class used for notifying all clients from different IP addresses.

Technical facts

 

 

 

 

 

 

./CppWtServerPusher/CppWtServerPusher.pri

 

INCLUDEPATH += \
    ../../Classes/CppWtServerPusher

SOURCES += \
    ../../Classes/CppWtServerPusher/wtserverpusher.cpp \
    ../../Classes/CppWtServerPusher/wtserverpusherclient.cpp

HEADERS  += \
    ../../Classes/CppWtServerPusher/wtserverpusher.h \
    ../../Classes/CppWtServerPusher/wtserverpusherclient.h

OTHER_FILES += \
    ../../Classes/CppWtServerPusher/Licence.txt

 

 

 

 

 

./CppWtServerPusher/wtserverpusher.h

 

//---------------------------------------------------------------------------
/*
WtServerPusher, server to broadcast to all its WtServerPusherClients
Copyright (C) 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/CppWtServerPusher.htm
//---------------------------------------------------------------------------
#ifndef WTSERVERPUSHER_H
#define WTSERVERPUSHER_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/function.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp>
#pragma GCC diagnostic pop

namespace ribi {

struct WtServerPusherClient;


///A Server that broadcasts its messages
struct WtServerPusher
{
  WtServerPusher(const WtServerPusher&) = delete;
  WtServerPusher& operator=(const WtServerPusher&) = delete;

  ///Let a WtServerPusherClient have its supplied function called by WtServerPusher::Run
  void Connect(WtServerPusherClient * const client, const boost::function<void()>& function);

  ///Stop a WtServerPusherClient have its supplied function called by TimePollServer::Run
  void Disconnect(const WtServerPusherClient* const client);

  ///Obtain the only instace to WtServerPusher
  static WtServerPusher * GetInstance();

  ///Get the version of this class
  static std::string GetVersion();

  ///Get the version history of this class
  static std::vector<std::string> GetVersionHistory();

  ///Post calls all WtServerPusherClients' supplied functions
  void Post();

private:
  //Connection is a non-copyable POD
  struct Connection
  {
    Connection(
      const std::string& session_id,
      WtServerPusherClient * 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;
    WtServerPusherClient * const m_client;
    const boost::function<void()> m_function;
  };

  ///WtServerPusher constructor, which is private, because WtServerPusher follows
  ///the Singleton design pattern
  WtServerPusher();

  ///WtServerPusher destructor
  ~WtServerPusher();

  ///Only let a smart pointer (that is, m_instance) delete WtServerPusher
  friend void boost::checked_delete<>(WtServerPusher*);

  ///All connections to the WtServerPusherClients
  std::vector<boost::shared_ptr<Connection> > m_connections;

  ///The WtServerPusher its only instance
  static boost::scoped_ptr<WtServerPusher> m_instance;

  ///A mutex
  mutable std::mutex m_mutex;
};

} //~namespace ribi

#endif // WTSERVERPUSHER_H

 

 

 

 

 

./CppWtServerPusher/wtserverpusher.cpp

 

//---------------------------------------------------------------------------
/*
WtServerPusher, server to broadcast to all its WtServerPusherClients
Copyright (C) 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/CppWtServerPusher.htm
//---------------------------------------------------------------------------
#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>

#include "wtserverpusher.h"
#pragma GCC diagnostic pop

boost::scoped_ptr<ribi::WtServerPusher> ribi::WtServerPusher::m_instance;

ribi::WtServerPusher::WtServerPusher()
  : m_connections{},
    m_mutex{}
{

}

ribi::WtServerPusher::~WtServerPusher()
{

}

void ribi::WtServerPusher::Connect(
   WtServerPusherClient * const client,
   const boost::function<void()>& function)
{
  std::lock_guard<std::mutex> lock(m_mutex);

  boost::shared_ptr<Connection> connection {
    new Connection(
      Wt::WApplication::instance()->sessionId(),
      client,
      function
    )
  };

  m_connections.push_back(connection);
}

void ribi::WtServerPusher::Disconnect(const WtServerPusherClient* 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::WtServerPusher * ribi::WtServerPusher::GetInstance()
{
  if (!m_instance) m_instance.reset(new WtServerPusher);
  return m_instance.get();
}

std::string ribi::WtServerPusher::GetVersion()
{
  return "1.0";
}

std::vector<std::string> ribi::WtServerPusher::GetVersionHistory()
{
  return {
    "2011-08-05: version 1.0: initial version"
  };
}

void ribi::WtServerPusher::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);

  for (auto c: m_connections)
  {
    Wt::WServer::instance()->post(c->m_session_id, c->m_function);
    };
}

 

 

 

 

 

./CppWtServerPusher/wtserverpusherclient.h

 

//---------------------------------------------------------------------------
/*
WtServerPusherClient, client of WtServerPusher
Copyright (C) 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/CppWtServerPusher.htm
//---------------------------------------------------------------------------
#ifndef WTSERVERPUSHERCLIENT_H
#define WTSERVERPUSHERCLIENT_H

#include <string>
#include <vector>

namespace ribi {

///WtServerPusherClient is a client responding to WtServerPusher
///and to be used as a base class
struct WtServerPusherClient
{
  virtual ~WtServerPusherClient();

  ///Get the version of this class
  static std::string GetVersion();

  ///Get the version history of this class
  static std::vector<std::string> GetVersionHistory();

  ///OnServerPush is called when the WtServerPusher is posted to
  virtual void OnServerPush() = 0;

  protected:
  ///WtServerPusherClient constructor is protected
  ///because it is to be used as a base class
  WtServerPusherClient();

  private:
  ///Respond to the server
  void OnServer();
};

} //~namespace ribi

#endif // WTSERVERPUSHERCLIENT_H

 

 

 

 

 

./CppWtServerPusher/wtserverpusherclient.cpp

 

//---------------------------------------------------------------------------
/*
WtServerPusherClient, client of WtServerPusher
Copyright (C) 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/CppWtServerPusher.htm
//---------------------------------------------------------------------------
#include "wtserverpusherclient.h"

#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 "wtserverpusher.h"
#pragma GCC diagnostic pop

ribi::WtServerPusherClient::WtServerPusherClient()
{
  Wt::WApplication::instance()->enableUpdates(true);
  WtServerPusher::GetInstance()->Connect(
    this,boost::bind(&ribi::WtServerPusherClient::OnServer,this));

  //Never call virtual functions during construction or destruction
  //Scott Meyers, Effective C++, item 9
  //OnServer();
}

ribi::WtServerPusherClient::~WtServerPusherClient()
{
  Wt::WApplication::instance()->enableUpdates(false);
  WtServerPusher::GetInstance()->Disconnect(this);
}

std::string ribi::WtServerPusherClient::GetVersion()
{
  return "1.0";
}

std::vector<std::string> ribi::WtServerPusherClient::GetVersionHistory()
{
  return {
    "2011-07-27: version 1.0: initial version"
  };
}

void ribi::WtServerPusherClient::OnServer()
{
  OnServerPush();
  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