Been trying to figure out how to properly handle custom events in conjunction with std::thread, haven't been able to find any code without wxThread. As i understand i need to use wxQueueEvent, but my problem is how to get the wxEvtHandler pointer to the class holding the thread. The bellow code passes a pointer of the class where i have the "onErrorEvent" function, this compiles and works, but I'm not sure if that's a "legal" way of doing it. It feels like a bad idea to use the pointer that way idk. All i want to know is if it will work hehe, doesn't need to be perfect textbook worthy code.
#include "cMain.h"
#include <iostream>
#include <thread>
using namespace std;
const int myEvtId=10000;
const int writeEvtId=10001;
wxDEFINE_EVENT(MY_EVT,wxCommandEvent);
wxDEFINE_EVENT(WRITE_EVT,wxCommandEvent);
wxBEGIN_EVENT_TABLE(cMain,wxFrame)
EVT_COMMAND(myEvtId,MY_EVT,cMain::onErrorEvent)
EVT_COMMAND(writeEvtId,WRITE_EVT,cMain::onWriteEvent)
wxEND_EVENT_TABLE()
class threadClass
{
public:
void startThread(wxEvtHandler *evtHandle)
{
threadState=true;
thr=thread(&threadClass::threadFn,this,evtHandle);
}
void endThread()
{
if(threadState)
{
threadState=false;
thr.join();
}
}
private:
bool threadFn(wxEvtHandler *evtHandle)
{
while(threadState)
{
if(error)
{
//Error occurred
wxCommandEvent *evt=new wxCommandEvent(MY_EVT,myEvtId);
wxQueueEvent(evtHandle,evt);
return false;
}
else
{
//Otherwise write data
wxCommandEvent *evt=new wxCommandEvent(WRITE_EVT,writeEvtId);
evt->SetString("Data to be written");
wxQueueEvent(evtHandle,evt);
}
this_thread::sleep_for(chrono::milliseconds(500));
}
return true;
}
private:
thread thr;
bool threadState=false;
bool error=false;
};
threadClass thrClass;
cMain::cMain() : wxFrame(nullptr,wxID_ANY,"wxWidgets template",wxPoint(30,30),wxSize(420,520))
{
txt1=new wxTextCtrl(this,wxID_ANY,"",wxPoint(20,20),wxSize(300,400),wxTE_READONLY | wxTE_MULTILINE);
wxButton *btn1=new wxButton(this,wxID_ANY,"Button 1",wxPoint(160,430),wxSize(80,40));
thrClass.startThread(this);
}
cMain::~cMain()
{
thrClass.endThread();
}
void cMain::onErrorEvent(wxCommandEvent &evt)
{
//Handle Error
thrClass.endThread();
}
void cMain::onWriteEvent(wxCommandEvent &evt)
{
//Write data
txt1->AppendText(evt.GetString()+'\n');
}
I'm using std:thread so it's compatible with existing code I've already written, so I'd rather not rewrite it with wxThread instead.
//Benji
**Edit - I revised the code to include my method of printing to the textCtrl ui element.
Related
I'm trying to put a bunch of sounds in a std::vector because it's very convenient.
I'm using an auxiliary variable called laser, load the sound into it and, if it's everything ok, push_back into the vector.
When I try to play any the sound, nothing happens, not even error messages which should be printed if anything goes wrong.
Just for curiosity I made laser static and voilá, it works flawlessly (or it seems to).
I'd like to know why.
Header file:
// audio_system.h
#ifndef KUGE_HEADERS_AUDIO_SYSTEM_H_
#define KUGE_HEADERS_AUDIO_SYSTEM_H_
#include "event.h"
#include "system.h"
#include "../sdl2_wrappers/sdl2_wrappers.h"
#include "../include/resources_path.h"
#include <vector>
namespace kuge {
class AudioSystem : virtual public System {
public:
AudioSystem(EventBus& bus): System(bus) {}
void handleEvent(const Event& event);
static bool loadResources();
private:
static void generateRandomSequence();
static std::vector<ktp::SDL2_Sound> lasers_;
};
} // end namespace kuge
#endif // KUGE_HEADERS_AUDIO_SYSTEM_H_
cpp file:
#include "event_bus.h"
#include "audio_system.h"
std::vector<ktp::SDL2_Sound> kuge::AudioSystem::lasers_{};
void kuge::AudioSystem::generateRandomSequence() {}
void kuge::AudioSystem::handleEvent(const Event& event) {
switch (event.getType()) {
case EventTypes::LaserFired:
if (lasers_[0].play() == -1) {
ktp::logSDLError("laser_.play");
}
break;
default:
break;
}
}
bool kuge::AudioSystem::loadResources() {
static ktp::SDL2_Sound laser{}; // here! If I don't make this static, nothing happens
if (!laser.loadSound(ktp::getResourcesPath() + "sounds/laser2.wav")) {
return false;
} else {
lasers_.push_back(laser);
}
ktp::logMessage("AudioSystem: resources loaded.");
return true;
}
OK, so following the advices from the comments, I've made the following changes to make ktp::SDL2_Sound class follow the rule of 0 and now it works without the need to set the laser variable to static. This solves the problem, but I'm still not sure why it worked being static.
class SDL2_Sound {
public:
//~SDL2_Sound() { free(); } // now I don't need any destructor
bool loadSound(const std::string& path);
int play(int loops = 0);
private:
void free();
// Mix_Chunk* sound_ = nullptr; // old raw pointer
std::shared_ptr<Mix_Chunk> sound_{};
};
/* void ktp::SDL2_Sound::free() {
if (sound_ != nullptr) {
Mix_FreeChunk(sound_);
sound_ = nullptr;
}
} */
bool ktp::SDL2_Sound::loadSound(const std::string& path) {
//free();
sound_.reset(Mix_LoadWAV(path.c_str()), &Mix_FreeChunk);
//sound_ = Mix_LoadWAV(path.c_str());
if (sound_ == nullptr) {
ktp::logSDLError("Mix_LoadWAV", path);
return false;
}
return true;
}
This is a fairly involved question, and unfortunately may involve compiling and running some code on your machine. Moreover, it's neither pure Objective-C nor it's C++, but rather using C++ from within Objective-C (i believe one might call it Objective-C++).
So, I'm using this library in my code. There's a class called ThreadsafeFace. For simplicity, one should think of it as an asynchronous socket (because that's what it uses underneath, in fact - unix socket). But the code I'm dealing with doesn't even get to the point where socket is being used for sending or receiving data.
Anyway, I have a C++ wrapper class FaceProcessor which looks like this:
FaceProcessor.h:
#include <stdio.h>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
namespace ndn {
class Face;
}
class FaceProcessorImpl;
class FaceProcessor {
public:
FaceProcessor(std::string host);
~FaceProcessor();
void start();
void stop();
bool isProcessing();
// non blocking
void dispatchSynchronized(boost::function<void(boost::shared_ptr<ndn::Face>)> dispatchBlock);
// blocking
void performSynchronized(boost::function<void(boost::shared_ptr<ndn::Face>)> dispatchBlock);
static boost::shared_ptr<FaceProcessor> forLocalhost();
private:
boost::shared_ptr<FaceProcessorImpl> _pimpl;
};
FaceProcessor.cpp:
#include "face-processor.hpp"
#include <boost/function.hpp>
#include <boost/asio.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <ndn-cpp/threadsafe-face.hpp>
using namespace ndn;
using namespace boost;
using namespace boost::asio;
class FaceProcessorImpl : public enable_shared_from_this<FaceProcessorImpl>{
public:
FaceProcessorImpl(std::string host);
~FaceProcessorImpl();
void start();
void stop();
bool isProcessing();
// non blocking
void dispatchSynchronized(boost::function<void(boost::shared_ptr<ndn::Face>)> dispatchBlock);
// blocking
void performSynchronized(boost::function<void(boost::shared_ptr<ndn::Face>)> dispatchBlock);
bool initFace();
void runFace();
private:
std::string host_;
shared_ptr<io_service::work> ioWork_;
io_service io_;
shared_ptr<Face> face_;
thread t_;
bool isRunningFace_;
};
shared_ptr<FaceProcessor>
FaceProcessor::forLocalhost()
{
return make_shared<FaceProcessor>("localhost");
}
FaceProcessor::FaceProcessor(std::string host):
_pimpl(make_shared<FaceProcessorImpl>(host))
{
if (_pimpl->initFace())
_pimpl->runFace();
else
throw std::runtime_error("couldn't initialize face object");
}
FaceProcessor::~FaceProcessor() {
_pimpl->stop();
_pimpl.reset();
}
void FaceProcessor::start() { _pimpl->start(); }
void FaceProcessor::stop() { _pimpl->stop(); }
bool FaceProcessor::isProcessing() { return _pimpl->isProcessing(); }
void FaceProcessor::dispatchSynchronized(function<void (shared_ptr<Face>)> dispatchBlock)
{
return _pimpl->dispatchSynchronized(dispatchBlock);
}
void FaceProcessor::performSynchronized(function<void (shared_ptr<Face>)> dispatchBlock)
{
return _pimpl->performSynchronized(dispatchBlock);
}
//******************************************************************************
FaceProcessorImpl::FaceProcessorImpl(std::string host):host_(host)
{
}
FaceProcessorImpl::~FaceProcessorImpl()
{
stop();
}
void FaceProcessorImpl::start()
{
if (!isRunningFace_)
if (initFace())
runFace();
}
void FaceProcessorImpl::stop()
{
if (isRunningFace_)
{
isRunningFace_ = false;
face_->shutdown();
std::cout << "work reset" << std::endl;
ioWork_.reset();
std::cout << "t join" << std::endl;
t_.join();
std::cout << "stopped" << std::endl;
}
}
bool FaceProcessorImpl::isProcessing()
{
return isRunningFace_;
}
void FaceProcessorImpl::dispatchSynchronized(boost::function<void (boost::shared_ptr<ndn::Face>)> dispatchBlock)
{
if (isRunningFace_)
{
shared_ptr<Face> f = face_;
io_.dispatch([dispatchBlock, f](){
dispatchBlock(f);
});
}
}
void FaceProcessorImpl::performSynchronized(boost::function<void (boost::shared_ptr<ndn::Face>)> dispatchBlock)
{
if (isRunningFace_)
{
if (this_thread::get_id() == t_.get_id())
dispatchBlock(face_);
else
{
mutex m;
unique_lock<mutex> lock(m);
condition_variable isDone;
atomic<bool> doneFlag(false);
shared_ptr<Face> face = face_;
io_.dispatch([dispatchBlock, face, &isDone, &doneFlag](){
dispatchBlock(face);
doneFlag = true;
isDone.notify_one();
});
isDone.wait(lock, [&doneFlag](){ return doneFlag.load(); });
}
}
}
bool FaceProcessorImpl::initFace()
{
try {
if (host_ == "localhost")
face_ = make_shared<ThreadsafeFace>(io_);
else
face_ = make_shared<ThreadsafeFace>(io_, host_.c_str());
}
catch(std::exception &e)
{
// notify about error
return false;
}
return true;
}
void FaceProcessorImpl::runFace()
{
ioWork_ = make_shared<io_service::work>(io_);
isRunningFace_ = false;
shared_ptr<FaceProcessorImpl> self = shared_from_this();
t_ = thread([self](){
self->isRunningFace_ = true;
while (self->isRunningFace_)
{
try {
std::cout << "io run" << std::endl;
self->io_.run();
std::cout << "io run completed" << std::endl;
self->isRunningFace_ = false;
}
catch (std::exception &e) {
// notify about error and try to recover
if (!self->initFace())
self->isRunningFace_ = false;
}
}
});
while (!isRunningFace_) ;
}
As can be seen, the wrapper hides io_service-related complexity, allowing client code to simply create processor, call start and stop at will in order to execute runloop of io_service. Whenever created, FaceProcessor starts running automatically, and stops itself upon destruction. Stopping is performed in, what I believe, a graceful manner - no calls to io_service::stop (as it may prevent scheduled handlers from being executed), but instead io_service::work is reset and thread::join() is invoked in order to wait for full thread completion.
Now, to the question.
The test code itself is fairly simple:
{
boost::shared_ptr<FaceProcessor> f = FaceProcessor::forLocalhost();
sleep(3);
}
which means, that FaceProcessor should finish in graceful manner with no problems. One can try out this code from the latest commit of this branch of the library (please, see instructions on how to build the library, it should be fairly straightforward) and executing bin/test-get-async-threadsafe example.
Now, the problem is, when I test the exact same code in Objective-C, it deadlocks, i.e. for some reason, io_service::run never returns. I use Xcode Unit Tests for testing this code and the test case looks like this:
FaceProcessorTests.mm:
#include "face-processor.hpp"
using namespace boost;
using namespace ndn;
#interface FaceProcessorTests : XCTestCase
#end
#implementation FaceProcessorTests
-(void)testTestProcessor
{
shared_ptr<FaceProcessor> f = FaceProcessor::forLocalhost();
sleep(3);
}
#end
My original FaceProcessor class was written in Objective-C++ (Objective-C with boost::asio::io_service and boost::thread) and I literally spent a week debugging this case, adding debug output to io_service (BOOST_ASIO_ENABLE_HANDLER_TRACKING) and underlying ThreadsafeFace object from the library. When I realized that exact same code works in C++, my final effort was to port FaceProcessor code over to pure C++ and use this class in Objective-C wrapper class. However this didn't help - the code still deadlocks, io_service::run() does not return in Objective-C environment.
I can't figure out why is this happening. Quite possibly, I'm just missing something fundamentally simple. One thing I noticed - when I comment out all code from FaceProcessor related to face_, nothing deadlocks in Objective-C. Since Face uses just socket underneath (in fact, it's boost::asio::local::stream_protocol::socket) - could it be that sockets may work slightly differently in Objective-C runtime?
The environment is:
MacBook Pro (Retina, 15-inch, early 2013)
MacOS Sierra 10.12.3
Xcode Version 8.2.1 (8C1002)
The project is desktop application (not iOS)
Well, hi there.
I'm new to c++ and I'm having some issues that I'm not sure what is causing them.
This is my main:
#include "GameWindow.h"
int main(void)
{
GameWindow * game_window = new GameWindow(true);
/* loop the game */
while (game_window->GetRunning())
{
// update
game_window->Update();
// draw
game_window->Draw();
}
delete game_window;
return 0;
}
and this is my header:
class GameWindow
{
private:
bool _running;
//GLFWwindow* _window;
public:
void SetRunning(bool new_val);
bool GetRunning();
GameWindow(bool running);
void Draw();
void Update();
}
and my c++ file:
#include "GameWindow.h"
void GameWindow::SetRunning(bool new_val)
{
_running = new_val;
}
bool GameWindow::GetRunning()
{
return _running;
}
GameWindow::GameWindow(bool running) :
_running(running)
{
}
void GameWindow::Draw()
{
}
void GameWindow::Update()
{
}
While going through all of this I find it tough to find why Visual Studio refuse to compile this code.
It's raising errors about how 'SetRunning' is overloading a function which differs only in return values, and that the return type of main should be Int and not GameWindow, and with all of this I just went completely lost.
Tried to put 'SetRunning' as a comment to simplify the issue but instead it raised the same on 'GetRunning' instead.
I'm guessing it's a really stupid mistake that is easy to fix, but still, can't find it.
Thank you for your time, and I'll appreciate any kind of help.
Missing ; at the end of class definition.
class GameWindow
{
// .....
}; // Missing semi-colon
Missing ; in class defination
{
};
because of this when you include the file in program then compiler not found the end of the class hence it says return type of main should be int not GameWindow
I am very new to C++.
I have a class, and I want to create a thread inside a class's function. And that thread(function) will call and access the class function and variable as well.
At the beginning I tried to use Pthread, but only work outside a class, if I want to access the class function/variable I got an out of scope error.
I take a look at Boost/thread but it is not desirable because of I don't want to add any other library to my files(for other reason).
I did some research and cannot find any useful answers.
Please give some examples to guide me. Thank you so much!
Attempt using pthread(but I dont know how to deal with the situation I stated above):
#include <pthread.h>
void* print(void* data)
{
std::cout << *((std::string*)data) << "\n";
return NULL; // We could return data here if we wanted to
}
int main()
{
std::string message = "Hello, pthreads!";
pthread_t threadHandle;
pthread_create(&threadHandle, NULL, &print, &message);
// Wait for the thread to finish, then exit
pthread_join(threadHandle, NULL);
return 0;
}
You can pass a static member function to a pthread, and an instance of an object as its argument. The idiom goes something like this:
class Parallel
{
private:
pthread_t thread;
static void * staticEntryPoint(void * c);
void entryPoint();
public:
void start();
};
void Parallel::start()
{
pthread_create(&thread, NULL, Parallel::staticEntryPoint, this);
}
void * Parallel::staticEntryPoint(void * c)
{
((Parallel *) c)->entryPoint();
return NULL;
}
void Parallel::entryPoint()
{
// thread body
}
This is a pthread example. You can probably adapt it to use a std::thread without much difficulty.
#include <thread>
#include <string>
#include <iostream>
class Class
{
public:
Class(const std::string& s) : m_data(s) { }
~Class() { m_thread.join(); }
void runThread() { m_thread = std::thread(&Class::print, this); }
private:
std::string m_data;
std::thread m_thread;
void print() const { std::cout << m_data << '\n'; }
};
int main()
{
Class c("Hello, world!");
c.runThread();
}
Before I present the code which is found at the bottom of this post I would like to talk about the issue and the fix's that I do not desire. Okay basically I've created a GUI from scratch sort of and one requirement I wanted for this was allow components to have their own click executions so if i click a button or tab etc.. It would call Component->Execute(); Well normally you would do something like a switch statement of ids and if that components ID equaled n number then it would perform this action. Well that seemed kinda dumb to me and I thought there has to be a better way. I eventually tried to incorporate a feature in JAVA where you would do like Component.AddActionListener(new ActionListener( public void execute(ActionEvent ae) { })); or something like that and I thought that this feature has to be possible in C++. I eventually came across storing void functions into a variable in which could be executed at any time and modified at any time. However I hadn't noticed an issue and that was this only worked with static functions. So below you'll see my problem. I've patched the problem by using a pointer to SomeClass however this would mean having an individual function call for every class type is there no way to store a function callback to a non-static class member without doing the below strategy? and instead doing a strategy like the commented out code?
//Main.cpp
#include <iostream> //system requires this.
#include "SomeClass.h"
void DoSomething1(void)
{
std::cout << "We Called Static DoSomething1\n";
}
void DoSomething2(void)
{
std::cout << "We Called Static DoSomething2\n";
}
int main()
{
void (*function_call2)(SomeClass*);
void (*function_call)() = DoSomething1; //This works No Problems!
function_call(); //Will Call the DoSomething1(void);
function_call = DoSomething2; //This works No Problems!
function_call(); //Will Call the DoSomething2(void);
SomeClass *some = new SomeClass(); //Create a SomeClass pointer;
function_call = SomeClass::DoSomething3; //Static SomeClass::DoSomething3();
function_call(); //Will Call the SomeClass::DoSomething3(void);
//function_call = some->DoSomething4; //Non-Static SomeClass::DoSomething4 gives an error.
//function_call(); //Not used because of error above.
function_call2 = SomeClass::DoSomething5; //Store the SomeClass::DoSomething(SomeClass* some);
function_call2(some); //Call out SomeClass::DoSomething5 which calls on SomeClass::DoSomething4's non static member.
system("pause");
return 0;
}
//SomeClass.hpp
#pragma once
#include <iostream>
class SomeClass
{
public:
SomeClass();
~SomeClass();
public:
static void DoSomething3(void);
void DoSomething4(void);
static void DoSomething5(SomeClass* some);
};
//SomeClass.cpp
#include "SomeClass.h"
SomeClass::SomeClass(void)
{
}
SomeClass::~SomeClass(void)
{
}
void SomeClass::DoSomething3(void)
{
std::cout << "We Called Static DoSomething3\n";
}
void SomeClass::DoSomething4(void)
{
std::cout << "We Called Non-Static DoSomething4\n";
}
void SomeClass::DoSomething5(SomeClass *some)
{
some->DoSomething4();
}
Secondary Fix for what I'll do not an exact answer I wanted but it meets my needs for now along with allowing additional features which would have become overly complicate had this not existed.
//Component.hpp
#pragma once
#include <iostream>
#include <windows.h>
#include <d3dx9.h>
#include <d3d9.h>
#include "Constants.hpp"
#include "ScreenState.hpp"
#include "ComponentType.hpp"
using namespace std;
class Component
{
static void EMPTY(void) { }
static void EMPTY(int i) { }
public:
Component(void)
{
callback = EMPTY;
callback2 = EMPTY;
callback_id = -1;
}
Component* SetFunction(void (*callback)())
{
this->callback = callback;
return this;
}
Component* SetFunction(void (*callback2)(int), int id)
{
this->callback_id = id;
this->callback2 = callback2;
return this;
}
void execute(void)
{
callback();
callback2(callback_id);
}
}
The syntax for pointers-to-member-functions is as follows:
struct Foo
{
void bar(int, int);
void zip(int, int);
};
Foo x;
void (Foo::*p)(int, int) = &Foo::bar; // pointer
(x.*p)(1, 2); // invocation
p = &Foo::zip;
(x.*p)(3, 4); // invocation
Mind the additional parentheses in the function invocation, which is needed to get the correct operator precedence. The member-dereference operator is .* (and there's also ->* from an instance pointer).