Websocket++ websocket server class member function not recognised from ISR - c++

I'm using an Odroid (Raspi-like ARM Board) to run a small SPI-based radio chip that sends data to, among other things, a Websocket. This is applied using Websocket++: https://github.com/zaphoyd/websocketpp. I've bastardised one of the simple examples, which sends a server message to all clients. The program has a count_server class which handles the websocket, but also has an ISR handled by WiringPi which calls nested functions to handle different operations.
The issue I've got is that in order to send this message, the sending function must be in the count_server class as far as I can tell, to access client addresses etc. This class method is not accesible from inside my ISR, which handles all data received from the radio, so when I try to send a websocket message from inside the ISR I get the error:
error: 'webSocketServer' was not declared in this scope webSocketServer.sendLiveData();
The webSocketServer is an instance of the class count_server, instantiated in main(). Why can't the ISR 'see' the webSocketServer class.
One workaround is to poll inside the count() function, but this blocks the CPU and I'd rather leave it ready to perform other tasks.]
Here's the simplest example I could produce.
Requires Websocket++ and WiringPi for the attachInterrupt.
#include <cstdlib>
#include <unistd.h>
#include <iostream>
#include <sstream>
#include <string>
#include <RF24/RF24.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//Websocket++ includes
#include <mutex>
#include <set>
#include <thread>
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
//*/
//websocket++ declarations
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
class count_server {
public:
count_server() : m_count(0) {
m_server.init_asio();
m_server.set_open_handler(bind(&count_server::on_open,this,_1));
m_server.set_close_handler(bind(&count_server::on_close,this,_1));
}
void on_open(connection_hdl hdl) {
std::lock_guard<std::mutex> lock(m_mutex);
m_connections.insert(hdl);
}
void on_close(connection_hdl hdl) {
std::lock_guard<std::mutex> lock(m_mutex);
m_connections.erase(hdl);
}
void sendLiveData(){
std::stringstream ss;
ss << "foobar";
for (auto it : m_connections) {
m_server.send(it,ss.str(),websocketpp::frame::opcode::text);
}
}
void count() {//simple loop thread, most likely not needed, but in working example so lef
t for time being
while (1) {
sleep(1000);
}
}
void run(uint16_t port) {
m_server.listen(port);
m_server.start_accept();
m_server.run();
}
private:
typedef std::set<connection_hdl,std::owner_less<connection_hdl>> con_list;
int m_count;
server m_server;
con_list m_connections;
std::mutex m_mutex;
};
/****************** Raspberry Pi ***********************/
int interruptPin = 6; // GPIO pin for interrupts - interrupts have been edited to be handled
//by wiringPi, so #6 is used, not #103, check RF24/utility/SPIDEV/interrupt.c for info
int i=0;
/**************************************************************/
void addLiveData(){ //Live data buffer handler + calls sending function when buffer hits max
webSocketServer.sendLiveData();
}
void intHandler(){//when radio chip IRQ goes Low, something happened, this handles it
addLiveData();//recvd = 2;//flag that the data is live data
}
int main(){
attachInterrupt(interruptPin, INT_EDGE_FALLING, &intHandler); //Attach interrupt to bcm p
in 23
count_server webSocketServer;
std::thread t(std::bind(&count_server::count,&webSocketServer));
webSocketServer.sendLiveData();
webSocketServer.run(8080);
}
'

Related

What is the recommended or most precise way, to call a function after a specific time?

I wrote a little program to launch and record a stereo setup of cameras. I would like to record a sequence of 100ms. The thing is: I don't know how to time the functions with the highest possible precision. I found the header <unistd.h> which includes the function usleep which can pause the execution for a specified microsecond interval. So in my program I'm doing something like this:
left_camera.start_recording();
right_camera.start_recording();
usleep(100000);
left_camera.stop_recording();
right_camera.stop_recording();
Is there a better way to ensure precise timing between the two functions?
You can also use std::this_thread::sleep_for (C++11)
#include <chrono>
#include <thread>
int main()
{
std::this_thread::sleep_for(std::chrono::nanoseconds(500));
}
sleep is not better way to implement a timer. You can use asio asynchronous timer feature from c++ boost library. you can create the timer and this shall call register function after timer expires
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
void func(const boost::system::error_code&)
{
std::cout << "in func" << std::endl;
}
int main()
{
boost::asio::io_service io;
boost::asio::deadline_timer t(io, boost::posix_time::seconds(0.1));
t.async_wait(&func);
io.run();
return 0;
}
Link libboost_system library while compiling
For more information refer:
https://www.boost.org/doc/libs/1_66_0/doc/html/boost_asio/tutorial.html

Is there a simple way to play a sound in a background thread using SFML

I am trying to play a song in a background thread of my GUI application so that the song doesn't block the GUI thread. Is there a simple way to do this with either std::thread or SFML Threads?
I have tried using std::thread for this, but it still blocks the GUI thread when I call my_thread.join().
Here is an example of what I want to do:
#include <thread>
#include <SFML/Audio.hpp>
#include <unistd.h>
#include <iostream>
void func() {
sf::Music music;
music.openFromFile("mysong.wav");
music.play();
// if I don't have usleep here the function exits immediately
// why is that exactly???
usleep(100000000);
}
int main() {
std::thread my_thread(func);
my_thread.join();
// this is where I would process events/build windows in GUI
while(1)
std::cout << "here"; // <--- Want this to run while song plays
}
in SFML you need to have a valid sf::Sound or sf::Music for music to play, when that variable gets destroyed you will no longer have a valid reference to that object a possible solution for the code you posted would be something like this:
#include <SFML/Audio.hpp>
#include <unistd.h>
#include <iostream>
class CAudio
{
sf::Music music;
public:
void func()
{
music.openFromFile("mysong.wav");
music.play();
}
sf::Status getStatus()
{
return music.getStatus();
}
}
int main() {
CAudio my_music;
my_music.func();
// http://www.sfml-dev.org/documentation/2.0/SoundSource_8hpp_source.php
while(my_music.getStatus() == sf::Status::Playing)
{
std::cout << "here"; // <--- Want this to run while song plays
}
}
Also, always use brackets, regardless if its a 1 line statement always use brackets, I know its allowed but it will make your life easier when you troubleshoot later on.

boost::property_tree::read_xml segfaults in an asio handler spawned using boost::asio::spawn

The following code crashes with a seg fault at boost::property_tree::read_xml() call.
This happens only if it's called inside of an io_service handler spawned using boost::asio::spawn(). If the handler is just posted, it works ok.
Is there a fix or workaround for this?
(boost 1.61)
#include <boost/asio/spawn.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <iostream>
#include <sstream>
#include <thread>
void process()
{
std::cerr << "start"<< std::endl;
std::istringstream is("<t>1</t>");
boost::property_tree::ptree pt;
boost::property_tree::read_xml(is, pt); // <<< seg fault here
std::cerr << std::endl << "end" << std::endl;
}
int main()
{
boost::asio::io_service io_service;
boost::asio::spawn(io_service, [] (boost::asio::yield_context y){
process();
});
io_service.run();
return 0;
}
After some digging we found that the seg fault is caused by coroutine's stack overflow because rapidxml parser used in boost::property_tree::read_xml() by default allocates 64KB on stack for the static memory pool within each xml document.
The solution is to reduce the size of the pool as follows:
#define BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE 512
#include <boost/property_tree/xml_parser.hpp>
Another solution would be to increase the stack size of coroutines.

Boost::Asio - Passing socket to second class

I am currently trying to get the following application to work:
Await incoming client connection.
Start async. timer in another class.
While the timer runs repeatedly, do other stuff such as async_read and async_write.
Current source code:
#define BOOST_ASIO_ENABLE_HANDLER_TRACKING
#include <WinSock2.h>
#include <Mswsock.h>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include "TimerClass.hpp"
using namespace boost::asio;
using namespace boost::asio::ip;
TimerClass *timerClass;
void acceptHandler(const boost::system::error_code &errorCode, tcp::socket *socket) {
timerClass = new TimerClass(socket);
timerClass->startTimer();
while(true) {
// Do other suff such as async_write, ...
}
}
int main(int argc, char** argv) {
io_service ioService;
tcp::socket socket(ioService);
tcp::acceptor acceptor{ ioService, tcp::endpoint{ tcp::v4(), 12345 } };
acceptor.listen();
acceptor.async_accept(socket, boost::bind(acceptHandler, _1, &socket));
ioService.run();
return EXIT_SUCCESS;
}
TimerClass.hpp:
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
using namespace boost::asio;
using namespace boost::posix_time;
class TimerClass {
public:
TimerClass(ip::tcp::socket *socket);
void startTimer();
void timerHandler(const boost::system::error_code& errorCode);
deadline_timer timer;
};
TimerClass.cpp:
#include <boost/bind.hpp>
#include "TimerClass.hpp"
TimerClass::TimerClass(ip::tcp::socket *socket) : timer(socket->get_io_service(), boost::posix_time::seconds(1)) {}
void TimerClass::startTimer() {
timer.async_wait(boost::bind(&TimerClass::timerHandler, this, boost::asio::placeholders::error));
}
void TimerClass::timerHandler(const boost::system::error_code& errorCode) {
timer.expires_at(timer.expires_at() + boost::posix_time::seconds(1));
timer.async_wait(boost::bind(&TimerClass::timerHandler, this, boost::asio::placeholders::error));
}
Handler Tracking Output:
#asio|1461070492.111630|0*1|socket#000000000021FBD0.async_accept
#asio|1461070498.527997|>1|ec=system:0
Questions:
Why won't it even call async_wait in startTimer? Debugging shows that startTimer gets called but I can't find anything in the Handler Tracking output. Why is that?
Am I correctly passing the socket to the TimerClass?
Without the infinite while(true) loop in the acceptHandler the acceptHandler returns but the application crashes before the io_service properly returns. How is that?
I compiled your code and it works for me (using boost version 1.54).
With your code I get the following output:
#asio|1461081908.437388|0*1|socket#003BFE2C.async_accept
#asio|1461081983.220840|>1|ec=system:0
#asio|1461081983.221817|1*2|deadline_timer#001C1318.async_wait
To make it run properly I had to remove the while(true) on your acceptHandler, obtaining the following output (added a std::cout inside the handler):
#asio|1461083707.104424|0*1|socket#0030FB6C.async_accept
#asio|1461083709.061824|>1|ec=system:0
#asio|1461083709.062803|1*2|deadline_timer#00641318.async_wait
#asio|1461083709.062803|<28158494073611763|
#asio|1461083710.064992|>2|ec=system:0
#asio|1461083710.064992|2|deadline_timer#00641318.cancel
#asio|1461083710.064992|2*3|deadline_timer#00641318.async_wait
TimerHandler executed...
#asio|1461083710.065971|<28169626628843099|
#asio|1461083711.065223|>3|ec=system:0
#asio|1461083711.065223|3|deadline_timer#00641318.cancel
#asio|1461083711.065223|3*4|deadline_timer#00641318.async_wait
TimerHandler executed...
I actually did this test using only the header TimerClass.hpp (defining the methods directly within it -I was lazy-) and it worked like a charm, the problem seems to be when using the .cpp file, that's why I asked if you were using include guards (not the issue though, already tested).
You should consider changing your design approach though, i.e. do not use blocking loops in you handlers, just call another asynchronous operation if needed (like async_read or async_write).
Take a look at this question and corresponding accepted answer for a nice server implementation idea. Or try to adapt some of the boost examples to your needs.
As per the segmentation fault you get when separating declaration from definition in the corresponding header and implementation files, you might want to check this other question.

ThreadPool with boost::asio does not quit?

I have the following minmal example of a thread pool made with boost::asio.
#include <queue>
#include <map>
#include <boost/shared_ptr.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/thread/thread.hpp>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> // remove me (only for io)
class ThreadPool
{
public:
void work_as_mainthread(void) { m_io_service.run(); }
ThreadPool(int poolSize = 4) : timer(m_io_service)
{
timer.expires_from_now(boost::posix_time::seconds(1)); // this line does not affect the problem
m_pWork.reset( new boost::asio::io_service::work(m_io_service) );
for ( int i = 0; i < poolSize; ++i)
m_threadGroup.create_thread( boost::bind(&boost::asio::io_service::run, &m_io_service) );
}
~ThreadPool()
{
m_pWork.reset();
m_threadGroup.join_all();
}
private:
boost::asio::io_service m_io_service;
boost::asio::deadline_timer timer;
boost::shared_ptr<boost::asio::io_service::work> m_pWork;
boost::thread_group m_threadGroup;
};
int main()
{
int n_threads = 2;
ThreadPool pool(n_threads);
pool.work_as_mainthread();
// this line is never reached...
return 0;
}
If you like, you can compile it like this:
g++ -Wall -g -lboost_thread -lboost_date_time -lboost_system main.cpp -o main
What makes me wonder is that the program does not stop. What I do is calling io_service::run, but without any "work" for it. io_services without work quit themselves, as said in the boost::asio docs. Now, why does my program never quit?
When you create a boost::asio::io_service::work object, that keeps the io_service from completing.
// This line keeps the io_service running
m_pWork.reset( new boost::asio::io_service::work(m_io_service) );
If you want it to stop, you would need to destroy that work object, like this:
// stop the worker(s)
m_pWork.reset();
It's up to you to find an appropriate time/place to do this. I would suggest calling timer.async_wait(), then in the handler you can reset your work object to see how this all should be working together.
See this portion of the documentation.