i'm writing server with will handle client connection, but i have problem moving class with thread inside to vector, i know if i had only thread i can move it to vector with std::move(), but here i have thread inside a class and i'm getting a lot of errors because thread is non-movable object.
Core.cpp:
#define OS_LINUX
#include <iostream>
#include <vector>
#include <string>
#include <thread>
#include <csignal>
#include <cstdlib>
#include <TCPServer/TCPServer.h>
#include <TCPServer/TCPServerConnection.h>
#include <ProcessManip/ProcessManip.h>
#include <Log/Log.h>
#include "ConnectionHandler.h"
//Global
bool TERMNINATE = false;//If true loops must end
const int PORT = 8822;
//Proto
void terminate(int sig);
void receive_message(ConnectionHandler *handler,string message);
using namespace std;
int main(int argc,char *argv[])
{
//Add Terminate handler
signal(SIGINT,terminate);
//Load configuration
Log::logDebug("Starting ...");
//Init
vector<ConnectionHandler> connections;
//Init modules
//Main
Log::logDebug("Running");
TCPServer server;
if(!server._bind(PORT))
return 1;
if(!server._listen())
return 2;
ProcessManip::cleanProcess(); /* Clean dead processes */
server.setBlocking(false);/* accept returns invalid socket if no connection */
Log::logDebug("Listening ...");
while(!TERMNINATE)
{
TCPServerConnection conn = server._accept();
if(!conn.isValid())
continue;
Log::logDebug((string)"Got connection from: "+conn.getAddress());/* Print IP address of client */
ConnectionHandler ch(&TERMNINATE,std::move(conn));
ch.setCallback(receive_message);
ch.start();
connections.push_back(std::move(ch)); //here is problem
/*connections.push_back(ConnectionHandler(&TERMNINATE,conn)); /* Add it to vector */
/*connections.back().setCallback(receive_message);
connections.back().start();*/
Log::logDebug("Connection added to vector");
}
server.setBlocking(true);
//Dispose
Log::logDebug("Stopping ...");
/*for(auto it = connections.begin();it!=connections.end();)
{
Log::logDebug((string)"Closed connection with: "+(*it).getConnection().getAddress());/* Print IP address of client */
//(*it).close(); /* Close connetion */
// it = connections.erase(it); /* Delete ConnectionHandler from vector */
// }
server._close();
Log::logDebug("Closed");
return 0;
}
void terminate(int sig)
{
//Change global value to true
TERMNINATE = true;
}
void receive_message(ConnectionHandler *handler,string message)
{
Log::logDebug((string)"Message ("+handler->getConnection().getAddress()+") : "+message);
}
ConnectionHandler.h
#ifndef EXT_CONNECTIONHANDLER
#define EXT_CONNECTIONHANDLER
#include <TCPServer/TCPServerConnection.h>
#include <thread>
#include <string>
#include <iostream>
#include <functional>
using namespace std;
class ConnectionHandler
{
public:
ConnectionHandler(bool *pMainTerminate,TCPServerConnection pConnection);
ConnectionHandler(TCPServerConnection pConnection);
~ConnectionHandler();
void start(); /* Start listening */
void stop(); /* Stop listening */
void close(); /* Stops listening + close connection */
void setConnection(TCPServerConnection pConnection);
TCPServerConnection getConnection();
void setCallback(function<void(ConnectionHandler*,string)> pFunction);
private:
bool *mainTerminate = NULL;
bool handler_terminate = false;
short status = 0;
TCPServerConnection connection;
bool needTerminate();
void run();
void waitForEnd();
function<void(ConnectionHandler*,string)> callback = NULL;
std::thread m_thread;
};
#endif
ConnectionHandler.cpp
#include "ConnectionHandler.h"
ConnectionHandler::ConnectionHandler(bool *pMainTerminate,TCPServerConnection pConnection)
{
this->mainTerminate = pMainTerminate;
this->connection = pConnection;
}
ConnectionHandler::ConnectionHandler(TCPServerConnection pConnection)
{
this->mainTerminate = NULL;
this->connection = pConnection;
}
ConnectionHandler::~ConnectionHandler()
{
this->close();
}
void ConnectionHandler::start()
{
m_thread = std::thread(&ConnectionHandler::run, this);
this->status = 1;
}
void ConnectionHandler::waitForEnd()
{
if(this->m_thread.joinable())
this->m_thread.join();
}
bool ConnectionHandler::needTerminate()
{
if(mainTerminate!=NULL)
return this->handler_terminate||*(this->mainTerminate);
else
return this->handler_terminate;
}
void ConnectionHandler::run()
{
string message = "";
string tmp = "";
this->connection.setBlocking(false); // So we can terminate any time
while(!this->needTerminate())
{
message = this->connection._receive();
if(message!="")
{
do
{
tmp = this->connection._receive();
message+=tmp;
}while(tmp!=""); /* If we get longer message than we can grab at one time */
this->connection._send(message); /* TODO Remove */
if(this->callback!=NULL)
this->callback(this,message);
message = "";
}
}
this->connection.setBlocking(true);
}
void ConnectionHandler::stop()
{
this->handler_terminate = true; /* Signals thread to stop */
this->waitForEnd();
this->status = 2;
}
void ConnectionHandler::close()
{
this->stop();
this->connection._close(); /* Close connection */
this->status = 3;
}
TCPServerConnection ConnectionHandler::getConnection()
{
return this->connection;
}
void ConnectionHandler::setConnection(TCPServerConnection pConnection)
{
this->connection = pConnection;
}
void ConnectionHandler::setCallback(function<void(ConnectionHandler*,string)> pFunction)
{
this->callback = pFunction;
}
Because this class violates the Rule Of Three, even if the std::thread issue gets addressed, other problems will likely appear; most likely taking the form of mysterious runtime bugs.
The compilation issue with std::thread is not the problem, it's merely a symptom of the real problem: this class should not be moved or copied. This class should only be new-constructed, then stuffed into a std::shared_ptr (or a reasonable facsimile) and stay there until it gets destroyed. Only the std::shared_ptr should be passed around, stuffed into a vector, etc...
Related
I am trying to make a menu for a project of mine. I have it working but when I run a function I want to be able to cancel it but when I run the function I can't get any inputs from my rotary encoder while it is still waiting. I think i need to cancel de function of the rotary encode but I don't now how to do that. How can I read from the rotary encoder while this function is playing?
main.cpp
#include <thread>
#include <iostream>
#include <chrono>
#include <fstream>
#include <vector>
#include <string>
#include <stdio.h>
#include <bcm2835.h>
#include <pigpio.h>
#include "rotary_encoder.hpp"
#include "i2cControl.hpp"
#include "lcdDriver.hpp"
using namespace std;
int pos = 1;
int maxmenu;
int minmenu;
int menustate;
void callback(int way);
void callbackS(int way);
int test(){
while (true){
//wait for conditions or cancel command
}
//run function
}
void homeMenu(){
maxmenu = 2;
minmenu = 1;
menustate = 0;
pos = 1;
//menu
}
void callback(int way){
int prevpos = pos;
pos = pos + way;
if (pos > maxmenu){
pos = minmenu;
}
if (pos < minmenu){
pos = maxmenu;
}
}
void callbackS(int way){
int switchState = way;
//home menu
if (menustate == 0){
if (pos = 1){
menustate == 1;
test();
homeMenu();
}
}
if (menustate == 1){
homeMenu();
}
}
int main(int argc, char *argv[]){
homeMenu();
if (gpioInitialise() < 0) return 1;
re_decoder dec(12, 16, 26, callback, callbackS);
while (true){
}
dec.re_cancel();
gpioTerminate();
return 0;
}
rotary_encoder.cpp
#include <iostream>
#include <thread>
#include <pigpio.h>
#include "rotary_encoder.hpp"
void re_decoder::_pulse(int gpio, int level, uint32_t tick)
{
if (gpio == mygpioA) levA = level; else levB = level;
if (gpio != lastGpio) /* debounce */
{
lastGpio = gpio;
if ((gpio == mygpioA) && (level == 1))
{
if (levB) (mycallback)(1);
}
else if ((gpio == mygpioB) && (level == 1))
{
if (levA) (mycallback)(-1);
}
}
}
void re_decoder::_pulseS(int gpio, int level, uint32_t tick)
{
levS = level;
if (levS) {
(mycallbackS)(2);
}
}
void re_decoder::_pulseEx(int gpio, int level, uint32_t tick, void *user)
{
/*
Need a static callback to link with C.
*/
re_decoder *mySelf = (re_decoder *) user;
mySelf->_pulse(gpio, level, tick); /* Call the instance callback. */
}
void re_decoder::_pulseExS(int gpio, int level, uint32_t tick, void *user)
{
/*
Need a static callback to link with C.
*/
re_decoder *mySelf = (re_decoder *) user;
mySelf->_pulseS(gpio, level, tick); /* Call the instance callback. */
}
re_decoder::re_decoder(int gpioA, int gpioB, int gpioS, re_decoderCB_t callback, re_decoderCB_t callbackS)
{
mygpioA = gpioA;
mygpioB = gpioB;
mygpioS = gpioS;
mycallback = callback;
mycallbackS = callbackS;
levA=0;
levB=0;
levS=0;
lastGpio = -1;
gpioSetMode(gpioA, PI_INPUT);
gpioSetMode(gpioB, PI_INPUT);
gpioSetMode(gpioS, PI_INPUT);
/* pull up is needed as encoder common is grounded */
gpioSetPullUpDown(gpioA, PI_PUD_UP);
gpioSetPullUpDown(gpioB, PI_PUD_UP);
gpioSetPullUpDown(gpioS, PI_PUD_UP);
/* monitor encoder level changes */
gpioSetAlertFuncEx(gpioA, _pulseEx, this);
gpioSetAlertFuncEx(gpioB, _pulseEx, this);
gpioSetAlertFuncEx(gpioS, _pulseExS, this);
}
void re_decoder::re_cancel(void)
{
gpioSetAlertFuncEx(mygpioA, 0, this);
gpioSetAlertFuncEx(mygpioB, 0, this);
gpioSetAlertFuncEx(mygpioS, 0, this);
}
rotary_encoder.hpp
#ifndef ROTARY_ENCODER_HPP
#define ROTARY_ENCODER_HPP
#include <stdint.h>
typedef void (*re_decoderCB_t)(int);
class re_decoder
{
int mygpioA, mygpioB, mygpioS, levA, levB, levS, lastGpio;
re_decoderCB_t mycallback;
re_decoderCB_t mycallbackS;
void _pulse(int gpio, int level, uint32_t tick);
void _pulseS(int gpio, int level, uint32_t tick);
/* Need a static callback to link with C. */
static void _pulseEx(int gpio, int level, uint32_t tick, void *user);
static void _pulseExS(int gpio, int level, uint32_t tick, void *user);
public:
re_decoder(int gpioA, int gpioB, int gpioS, re_decoderCB_t callback, re_decoderCB_t callbackS);
/*
This function establishes a rotary encoder on gpioA and gpioB.
When the encoder is turned the callback function is called.
*/
void re_cancel(void);
/*
This function releases the resources used by the decoder.
*/
};
#endif
As I came to know creating and terminating thread abruptly
using pthread_kill() everytime is not a good way to do, so I am going
with suspend and resume method for a thread using thread1.suspend() and
thread1.resume(), whenever needed. How to do/implement this?
Take below LED blinking code for reference. During thread1.start() creating thread with suspended = false; is continuing as it is stuck in a while loop.
Calling thread1.suspend() has no effect.
#define on 1
#define off 0
void gpio_write(int fd, int value);
void* led_Flash(void* args);
class PThread {
public:
pthread_t threadID;
bool suspended;
int fd;
pthread_mutex_t m_SuspendMutex;
pthread_cond_t m_ResumeCond;
void start() {
suspended = false;
pthread_create(&threadID, NULL, led_Flash, (void*)this );
}
PThread(int fd1) { this->fd=fd1; }
~PThread() { }
void suspend() {
pthread_mutex_lock(&m_SuspendMutex);
suspended = true;
printf("suspended\n");
do {
pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
} while (suspended);
pthread_mutex_unlock(&m_SuspendMutex);
}
void resume() {
/* The shared state 'suspended' must be updated with the mutex held. */
pthread_mutex_lock(&m_SuspendMutex);
suspended = false;
printf("Resumed\n");
pthread_cond_signal(&m_ResumeCond);
pthread_mutex_unlock(&m_SuspendMutex);
}
};
void* led_Flash(void* args)
{
PThread* pt= (PThread*) args;
int ret=0;
int fd= pt->fd;
while(pt->suspended == false)
{
gpio_write(fd,on);
usleep(1);
gpio_write(fd,off);
usleep(1);
}
return NULL;
}
int main()
{
int fd1=1,fd2=2, fd3=3;
class PThread redLED(fd1);
class PThread amberLED(fd2);
class PThread greenLED(fd3);
redLED.start();
amberLED.start();
greenLED.start();
sleep(1);
redLED.suspend();
return 0;
}
Could some body help me, please?
After a little modification of above code , it seems working . Thanks guy for pointing out issues on above code, the changes are as follow.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<iostream>
#define on 1
#define off 0
void gpio_write(int fd, int value);
void* led_Flash(void* args);
class PThread {
public:
pthread_t threadID;
volatile int suspended;
int fd;
pthread_mutex_t lock;
PThread(int fd1)
{
this->fd=fd1;
this->suspended =1; //Initial state: suspend blinking untill resume call
pthread_mutex_init(&this->lock,NULL);
pthread_create(&this->threadID, NULL, led_Flash, (void*)this );
}
~PThread()
{
pthread_join(this->threadID , NULL);
pthread_mutex_destroy(&this->lock);
}
void suspendBlink() {
pthread_mutex_lock(&this->lock);
this->suspended = 1;
pthread_mutex_unlock(&this->lock);
}
void resumeBlink() {
pthread_mutex_lock(&this->lock);
this->suspended = 0;
pthread_mutex_unlock(&this->lock);
}
};
void gpio_write(int fd, int value)
{
if(value!=0)
printf("%d: on\n", fd);
else
printf("%d: off\n", fd);
}
void* led_Flash(void* args)
{
PThread* pt= (PThread*) args;
int fd= pt->fd;
while(1)
{
if(!(pt->suspended))
{
gpio_write(fd,on);
usleep(1);
gpio_write(fd,off);
usleep(1);
}
}
return NULL;
}
int main()
{
//Create threads with Initial state: suspend/stop blinking untill resume call
class PThread redLED(1);
class PThread amberLED(2);
class PThread greenLED(3);
// Start blinking
redLED.resumeBlink();
amberLED.resumeBlink();
greenLED.resumeBlink();
sleep(5);
// suspend/stop blinking
amberLED.suspendBlink();
sleep(5);
redLED.suspendBlink();
sleep(5);
amberLED.suspendBlink();
sleep(5);
redLED.resumeBlink();
pthread_exit(NULL);
return 0;
}
I used the following code to create a timer object in my c++ application running on a debian 8.
class Timer
{
private:
std::condition_variable cond_;
std::mutex mutex_;
int duration;
void *params;
public:
Timer::Timer(void (*func)(void*))
{
this->handler = func;
this->duration = 0;
this->params = NULL;
};
Timer::~Timer(){};
void Timer::start(int duree, void* handlerParams)
{
this->duration = duree;
this->params = handlerParams;
/*
* Launch the timer thread and wait it
*/
std::thread([this]{
std::unique_lock<std::mutex> mlock(mutex_);
std::cv_status ret = cond_.wait_for(mlock,
std::chrono::seconds(duration));
if ( ret == std::cv_status::timeout )
{
handler(params);
}
}).detach();
};
void Timer::stop()
{
cond_.notify_all();
}
};
It works correctly under gdb and under normal conditions, but in a load test of 30 requests or more, it crashes with the assertion :
nptl/pthread_mutex_lock.c:350: __pthread_mutex_cond_lock_full: Assertion `(-(e)) != 3 || !robust' failed.
I don't understand the cause of this assertion. Can anyone help me please ??
Thank you
Basically you have a detached thread that accesses the timer object, so it's likely that you destroyed the Timer object but the thread is still running and accessing it's member(mutex, conditional variable).
The assert itself says, from glibc source code, that the owner of the mutex has died.
Thanks a lot for your comments ! I'll try to change the thread detach, and do the load tests.
This is a MVCE of my problem, which is a part of a huge application.
/**
* \file Timer.hxx
* \brief Definition of Timer class.
*/
#include <chrono>
#include <thread>
#include <mutex>
#include <condition_variable>
class Timer
{
private:
std::condition_variable cond_;
std::mutex mutex_;
int duration;
void *params;
public:
Timer(void (*func)(void*));
~Timer();
void (*handler)(void*);
void start(int duree, void* handlerParams);
void stop();
};
/*
* Timer.cxx
*/
#include "Timer.hxx"
Timer::Timer(void (*func)(void*))
{
//this->set_handler(func, params);
this->handler = func;
this->duration = 0;
this->params = NULL;
}
Timer::~Timer()
{
}
void Timer::start(int duree, void* handlerParams)
{
this->duration = duree;
this->params = handlerParams;
/*
* Launch the timer thread and wait it
*/
std::thread([this]{
std::unique_lock<std::mutex> mlock(mutex_);
std::cv_status ret = cond_.wait_for(mlock, std::chrono::seconds(duration));
if ( ret == std::cv_status::timeout )
{
handler(params);
}
}).detach();
}
void Timer::stop()
{
cond_.notify_all();
}
/*
* MAIN
*/
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include "Timer.hxx"
using namespace std;
void timeoutHandler(void* params)
{
char* data= (char*)params;
cout << "Timeout triggered !! Received data is: " ;
if (data!=NULL)
cout << data << endl;
}
int main(int argc, char **argv)
{
int delay=5;
char data[20] ="This is a test" ;
Timer *t= new Timer(&timeoutHandler) ;
t->start(delay, data);
cout << "Timer started !! " << endl;
sleep(1000);
t->stop();
delete t;
cout << "Timer deleted !! " << endl;
return 0;
}
I'm trying to create a socket for my SDL server.
Problem is that I get an access violation crash because my socket called server is unable to open itself properly.
My class:
#pragma once
#include <SDL_net.h>
#include <thread>
#include <vector>
#include <string>
#include <iostream>
using namespace std;
const Uint16 SERVER_PORT = 1234;
const int TICKS_PER_SECOND = 1000;
const int REQUIRED_PLAYERS = 1;
class ServerTCP {
private:
//Thread data
thread *threadListen;
bool threadExit;
//Server data
IPaddress serverIP;
TCPsocket server;
vector <string> feedback;
//Client data
vector <TCPsocket> clients;
vector <string> events;
static void threadLoop(ServerTCP *self);
public:
ServerTCP();
~ServerTCP();
};
Source:
#include "ServerTCP.h"
ServerTCP::ServerTCP() {
printf("Starting server...\n");
if (SDLNet_ResolveHost(&serverIP, NULL, SERVER_PORT) == -1) {
printf("SDLNet_ResolveHost: %s\n", SDLNet_GetError());
}
server = SDLNet_TCP_Open(&serverIP);
if (!server) {
printf("SDLNet_TCP_Open: %s\n", SDLNet_GetError());
}
threadExit = false;
threadListen = new thread(&ServerTCP::threadLoop, this);
}
ServerTCP::~ServerTCP() {
printf("Shutting down server...\n");
threadExit = true;
threadListen->join();
for (int i = 0; i < clients.size(); i++) {
string warning = "Server has shut down, you was disconnected!\n";
SDLNet_TCP_Send(clients[i], warning.c_str(), warning.size());
SDLNet_TCP_Close(clients[i]);
}
SDLNet_TCP_Close(server);
}
void ServerTCP::threadLoop(ServerTCP *self) {
printf("Waiting for players...\n");
TCPsocket newClient;
//Run thread until orderered to stop
while (!self->threadExit) {
//Look for new clients
newClient = SDLNet_TCP_Accept(self->server);
if (newClient) {
self->clients.push_back(newClient);
string warning = "You have connected to the server!\n";
SDLNet_TCP_Send(newClient, warning.c_str(), warning.size());
printf("Player %i has connected!\n", self->clients.size());
}
if (self->clients.size() >= REQUIRED_PLAYERS) {
for (int i = 0; i < REQUIRED_PLAYERS; i++) {
string warning = "You found an opponent!\n";
SDLNet_TCP_Send(self->clients[i], warning.c_str(), warning.size());
SDLNet_TCP_Close(self->clients[i]);
}
}
}
}
Output:
Starting server...
SDLNet_TCP_Open: Couldn't create socket
Never mind, I forgot I had the SDLNet_Init function in my sub class i removed in the server file.
I am reading a message from a socket with C++ code and am trying to plot it interactively with matplotlib, but it seems Python code will block the main thread, no matter I use show() or ion() and draw(). ion() and draw() won't block in Python.
Any idea how to plot interactively with matplotlib in C++ code?
An example would be really good.
Thanks a lot.
You may also try creating a new thread that does the call to the
blocking function, so that it does not block IO in your main program
loop. Use an array of thread objects and loop through to find an unused
one, create a thread to do the blocking calls, and have another thread
that joins them when they are completed.
This code is a quick slap-together I did to demonstrate what I mean about
using threads to get pseudo asynchronous behavior for blocking functions...
I have not compiled it or combed over it very well, it is simply to show
you how to accomplish this.
#include <pthread.h>
#include <sys/types.h>
#include <string>
#include <memory.h>
#include <malloc.h>
#define MAX_THREADS 256 // Make this as low as possible!
using namespace std;
pthread_t PTHREAD_NULL;
typedef string someTypeOrStruct;
class MyClass
{
typedef struct
{
int id;
MyClass *obj;
someTypeOrStruct input;
} thread_data;
void draw(); //Undefined in this example
bool getInput(someTypeOrStruct *); //Undefined in this example
int AsyncDraw(MyClass * obj, someTypeOrStruct &input);
static void * Joiner(MyClass * obj);
static void * DoDraw(thread_data *arg);
pthread_t thread[MAX_THREADS], JoinThread;
bool threadRunning[MAX_THREADS], StopJoinThread;
bool exitRequested;
public:
void Main();
};
bool MyClass::getInput(someTypeOrStruct *input)
{
}
void MyClass::Main()
{
exitRequested = false;
pthread_create( &JoinThread, NULL, (void *(*)(void *))MyClass::Joiner, this);
while(!exitRequested)
{
someTypeOrStruct tmpinput;
if(getInput(&tmpinput))
AsyncDraw(this, tmpinput);
}
if(JoinThread != PTHREAD_NULL)
{
StopJoinThread = true;
pthread_join(JoinThread, NULL);
}
}
void *MyClass::DoDraw(thread_data *arg)
{
if(arg == NULL) return NULL;
thread_data *data = (thread_data *) arg;
data->obj->threadRunning[data->id] = true;
// -> Do your draw here <- //
free(arg);
data->obj->threadRunning[data->id] = false; // Let the joinThread know we are done with this handle...
}
int MyClass::AsyncDraw(MyClass *obj, someTypeOrStruct &input)
{
int timeout = 10; // Adjust higher to make it try harder...
while(timeout)
{
for(int i = 0; i < MAX_THREADS; i++)
{
if(thread[i] == PTHREAD_NULL)
{
thread_data *data = (thread_data *)malloc(sizeof(thread_data));
if(data)
{
data->id = i;
data->obj = this;
data->input = input;
pthread_create( &(thread[i]), NULL,(void* (*)(void*))MyClass::DoDraw, (void *)&data);
return 1;
}
return 0;
}
}
timeout--;
}
}
void *MyClass::Joiner(MyClass * obj)
{
obj->StopJoinThread = false;
while(!obj->StopJoinThread)
{
for(int i = 0; i < MAX_THREADS; i++)
if(!obj->threadRunning[i] && obj->thread[i] != PTHREAD_NULL)
{
pthread_join(obj->thread[i], NULL);
obj->thread[i] = PTHREAD_NULL;
}
}
}
int main(int argc, char **argv)
{
MyClass base;
base.Main();
return 0;
}
This way you can continue accepting input while the draw is occurring.
~~Fixed so the above code actually compiles, make sure to add -lpthread