Callback of request is never called when I put std::this_thread::sleep_for(1) - c++

I am trying to prevent entering in scene if some stuff from server are not loaded, I have flag bool
done = false;
CCHttpRequest *pRequest;
// initialization ....
pRequest->setResponseCallback(this, httpresponse_selector(SceneController::on_response));
CCHttpClient::getInstance()->send(pRequest);
pRequest->release();
while(!done) {
std::chrono::milliseconds duration(1);
std::this_thread::sleep_for(duration);
}
in function callback on_response I set
done = true;
what should ( but doesn't work ) break out of infinite loop.
Problem with this approach is that callback is never called ( breakpoint at the first line in callback is never reached ). When I comment while loop it called callback.
Does anyone know what is a problem and how to prevent further execution until I fetch data from server ?
Callstack when it works on break point inside callback

Callback is NOT another thread as you might be thinking. You trying hold current function execution 'till callback gets called'. That's not correct. You should return from it and allow callback to be called. This should do:
done = false;
CCHttpRequest *pRequest;
// initialization ....
pRequest->setResponseCallback(this, httpresponse_selector(SceneController::on_response));
CCHttpClient::getInstance()->send(pRequest);
pRequest->release();
if (!done)
{
return;
}
else
{
// Do here whatever you want to do after callback changes flag
}

All your code would be executed in Cocos thread, CCHttpRequest has its own thread to fetch data from server then when all data was fetched the callback you registered before would be called in cocos thread, too.
After the registration of callback, cocos thread continues to execute to your while, now the callback is not called (data isn't completed) your while will run forever. When the data is completed, callback need to be executed in cocos thread but you're seeing the while keep blocking it.
In async world (see here, and here, you must understand async), you cannot "prevent further execution until you fetch data from server" with the pattern you are using. Try to prevent it by your done variable in places that you want it does not be executed.
E.g:
done = false;
CCHttpRequest *pRequest;
// initialization ....
pRequest->setResponseCallback(this, httpresponse_selector(SceneController::on_response));
CCHttpClient::getInstance()->send(pRequest);
pRequest->release();
and then in any you don't want user to interact with your game interface, as in Touch:
void onTouchBegan(Event *pEvent, Touch *pTouch)
{
if (!done)
{
return false;
}
// code when `done == true`
}
void onTouchEnded(Event *pEvent, Touch *pTouch)
{
// Code here will not be executed if `onTouchBegan` return `false`
}
whenever onTouchBegan return false, no more of touch code will be executed then prevent your user from interacting with game's element.
Also to prevent buttons menu clicking, set disable to their parent Menu container: menu->setEnabled(false) then set back to enabled when fetching done.

Related

How to manage the deletion and recreation of a main frame and a working thread in a multithreaded application in wxWidgets

Introduction
I am new to multithreading. I have an created a GUI application in c++ on windows 10 using wxWidgets. A worker thread communicates in the background via sockets and appends events to some event handlers from the main thread (GUI); I have two available protocols for the communication, and I allow the user to choose among those at the beginning (before instantiating the thread). To append events, I have a few shared pointers on the event handlers; a bit like in this tutorial, where it keeps a pointer of the m_parent. To communicate with the working thread, I created a queue using a mutex and semaphore, also like in the tutorial. For now, everything works.
Now, I want to let the user change the protocol while the application runs. I have thus a menu with a related button. This button calls the following function (create_app()) that deletes the top window and the communication thread and recreates everything. That is where I have problems.
bool cApp::create_app() {
wxWindow* main_window = GetTopWindow();
// If there is already a window, delete everything before creation
if(main_window) {
//thread_communication->Wait(); // Should I wait for the thread to finish? I shouldn't
if (thread_communication->Delete() != wxTHREAD_NO_ERROR) { // Should I delete it since it should be destroyed when Entry is finished
std::cerr << "DELETE IMPOSSIBLE!" << std::endl;
return false;
}
if (main_window->Destroy() != wxTHREAD_NO_ERROR) { // Here I can't delete the window
std::cerr << "DELETE WINDOW IMPOSSIBLE!" << std::endl; // prints
return false;
}
SetTopWindow(NULL);
}
// Create everything
m_frame1 = new MainFrame(*this);
SetTopWindow(m_frame1);
m_frame1->Show();
std::vector<std::shared_ptr<wxEvtHandler>> evt_handlers;
m_frame1->get_handlers(evt_handlers);
// Construct the working thread with the evt handlers and the queue from the main window
thread_communication = std::unique_ptr<ThreadCom>(new ThreadCom(evt_handlers, m_frame1->get_queue());
wxThreadError err = thread_communication->Create();
...
err = thread_communication->Run();
...
return true;
}
bool cApp::OnInit() {
return create_app();
}
When the user click the related button, it calls this create_app function but before sends a task via the queue to the working thread with the highest priority (meaning it will be the next task achieved by it); afterwards, in the working thread, it exits after poping the task the while loop in Entry. Thus, the working thread should terminate there.
Problem
I have problem when deleting the thread and the application. I have memory leaks since, I guess, they share common material (pointers).
When I try to use Wait, I have first a assert !IsDetached. That is because I cannot wait for a detached thread. If I continue, the programm crashes (Access violation reading location) during the thread->Delete() call.
If I don't use Wait, the thread->Delete() call works fine. Afterwards, the program crashes at main_window->Destroy(); the return code is not ok thus it prints "DELETE WINDOW IMPOSSIBLE" with an Unhandled exception thrown: read access violation message.
So, how should I proceed? Should I implement destructors in the classes? How can I delete the thread and the app safely?
Thanks in advance for your help.

validating UpdateData(true) return value in MFC OnTimer routine

I am working on an MFC application(VS2017).
In that I have a made one second timer. Inside the OnTimer() routine along with my business logic I am calling UpdateData(FALSE) to show some runtime info back to UI.
Also, I have to get some user input from the UI for that inside the user Input Event handler, I am calling UpdateData(TRUE) and checking its return value in OnTimer routine.
Problem is since the timer is an independent entity here. Even though I have guarded the UpdateData(FALSE) inside OnTimer the UpdateData(FALSE) is getting executed for a blank user input, which crashes the program by calling assert.
/***SAMPLE Problem CODE****/`
void abc::OnEnUserInput()
{
IsvalidInput = UpdateData(TRUE);
}
void abc::OnTimer(UINT_PTR nIDEvent)
{
if (IsvalidInput == true)
{
UpdateData(FALSE);
}
}
Any help would be greatly appreciated!!!
Thanks.
Got my solution earlier itself but due to the busy schedule couldn't get time to share it.
for avoiding this issue I opened another dialogue box to receive the user input, since UpdatedData(FALSE) in OnTimer() is in background dialogue box so the user input in child dialog UpdateData(TRUE) will not interfare with background UpdatedData(FALSE).

MessageDialog in separate thread

In my current project I need to perform some calculations when a specific button is pressed, and while I perform these calculations, I want to show a Gtk::MessageDialog that simply states that calculations are being performed. So, I initialize the MessageDialog like this (for the moment just ignore that I actually don't need the pointer here):
Gtk::MessageDialog *waitdialog;
Gtk::MessageDialog dia("Processing", false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE, true);
dia.set_title("Wait.");
dia.set_transient_for(*(Gtk::Window *)this);
waitdialog = &dia;
Next I want to start a separate thread with the dialog:
std::thread dialog_thread(wait_dialog,waitdialog);
The wait_dialog method is defined as follows:
void wait_dialog(Gtk::MessageDialog *dialog){
dialog->run();
}
The problem now is, that even though the main window is darkened (because of set_transient_for), the message dialog is not visible. However, when I don't start a seperate thread, but just call waitdialog->run() instead, this will show the dialog properly (but will result in a loop).
So, the question is: why does the workaround with the separate thread not work? I can't make any sense of that :-(
GUI components are required to stay in the GUI loop. Your long running calculations belong in the thread. The calculation thread then signals back to the GUI thread to close the modal dialog. Also, you should use glib threads instead of std::threads. Here's how I would structure program:
// in header, member var dispatcher used to signal GUI thread
// and our member var thread
Glib::Dispatcher m_signalDone;
Glib::Thread* m_someThread;
...
// in constructor, hook up dispatcher event
m_signalDone.connect(sigc::mem_fun(this, &MyClass::OnDone));
...
// later when ready to kick off thread...
// show dialog or progess bar or something and kick off thread...
m_someThread = Glib::Thread::create(sigc::mem_fun(*this, &MyClass::CalcMethod), true);
...
void MyClass::CalcMethod()
{
// do your long running stuff...
// when done signal completion back to GUI
m_signalDone.emit();
}
...
void MyClass::OnDone()
{
// clean up dialog or progress bar or whatever
// kill thread
m_currentBackUpThread->join();
m_currentBackUpThread = NULL;
}

Why message loop doesn't block the GUI in windows app but does in Qt?

I'm working on a program using Qt, and some of my code is based on Windows samples. The problem I'm having, and something I don't quite understand is how the same code will block my Qt GUI while it will work totally fine in a windows app.
Here's an example. I have a program which gets some data from the camera, does some processing on it, then displays it on the screen. In Windows sample there's something like this:
// Create an event with these self-explanatory parameters
// This event signals when the next frame is ready to process
HANDLE frameEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr)
// Now run a while loop which magically doesn't block
HANDLE hEvents[1];
while (WM_QUIT != msg.message)
{
hEvents[0] = frameEvent;
DWORD dwEvent = MsgWaitForMultipleObjects(1, hEvents, FALSE, INFINITE, QS_ALLINPUT);
// If we have our event run some processing
if (WAIT_OBJECT_0 == dwEvent)
{
update();
}
// Else handle input or whatever
}
The update function looks something like this:
if (WAIT_OBJECT_0 = WaitForSingleObject(frameEvent, 0)
{
getTheFrame();
processTheFrame();
drawTheFrame();
}
If I try to implement it the same way in Qt everything will freeze and the while loop will just run forever. The solution I've got is to run the loop in separate thread (QThread) and emit a signal when new frame is ready, like this:
void Worker::run()
{
running_ = true;
while (running_)
{
if (WaitForSingleObject(frameEvent, 0) == WAIT_OBJECT_0)
{
emit signalFrame();
}
// This is necessary or it will still freeze!
usleep(15);
}
}
The signal is then connected to a slot which does similar job to the Update() method from the windows sample.
Now, this works fine, but only as long as processing a single frame can be done before the next frame is available.
As my processing went more complex and is slower then camera framerate, the program just stops responding. The exact same code in the windows sample still works fine, the framerate just drops, but everything is drawn and the GUI remains responsive.
Could someone explain what is going on, and what may be a possible solution?
The Win32 version calls MsgWaitForMultipleObjects. As its name should imply, it waits for either the specified objects to be signaled or for a window message (and since it's called with QS_ALLINPUT, any window message). Presumably the code also dispatches the window message afterward.
Your version calls WaitForSingleObject. As its name should imply, it waits on only the specified object. It won't unblock itself on window messages.

How to lock code execution in iOS application

Problem Description
I have a function StdString ShowLockScreen() in this function I call activateViewController function which shows some UI where user must enter PIN, just after calling activateViewController function I want to lock all processes until user will enter his PIN and press OK button on opened UI. Below you can see code which I try
Source code in iOS
StdString ShowLockScreen()
{
// Create a lock.
NSLock* theLock = [[NSLock alloc] init];
// Create a UI in which user must enter his PIN.
PinLockController* controller = [[PinLockController alloc] initWithStyle:PinLockTypeSet];
// Set delegate.
controller.delegate = m_Context;
// !!! Here I show a UI and just after that I lock my lock in order code stop executing there.
[controller activateViewController:nil];
#synchronized(theLock) {
[theLock lock];
}
NSLog(#"User in UI unlock the lock");
}
I want that my code stops then I call [theLock lock]; and after I will call [theLock unlock]; from my UI and code will continue executing. But it doesn't work in my case.
Source code in Android
I have write similar application in Android and here is code. I want to write same in iOS but I can;t find solution
Intent intent = new Intent(mCtx, SoftPinActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
SharedObject lock = new SharedObject("");
int lockId = SharedObject.acquireLockId(lock);
Logger.i(TAG, "lockId = " + lockId);
intent.putExtra(SharedObject.LOCK_ID, lockId);
intent.putExtra(SoftPinActivity.UI_ID, style);
synchronized (lock) {
mCtx.startActivity(intent);
try {
Logger.i(TAG, "lock.wait()...");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
Logger.i(TAG, "InterruptedException");
}
}
Logger.i(TAG, "lock.wait()...done");
SharedObject.releaseLockId(lockId);
String pin = lock.object();
Researches
I think I must use
NSCondition* condLock = [[NSCondition alloc] init];
[condLock wait];
and
[condLock signal];
but how to use this in my code ?
Answer to problem
You can lock threads using NSLock, but in your situation, this doesn't seem to be applicable. The reason being is that locking is primarily used to provide thread safety when data is accessed from multiple threads. What you're asking for is a domain level lock, which prevents the user from using the application unless they've typed in their PIN. These two concepts share the word "lock", but they're entirely different in their implementation. If you were to use NSLock and its related counterparts, you're forcing your implementation into separate threads purely to block user interaction, and risk complicating your project and pains in debugging (deadlocks much?).
Suggested solution
As the concept is a domain level locking mechanism, I suggest we keep it this way for its implementation. If you want it to be analogous to Android, then you'd need to create your own concept of a 'SharedObject' that everything else queries. If this object were to say "The user hasn't unlocked the application", then nothing will process. This keeps you away from manually managing threads, and frees threads up for when you really need them most (asynchronous processing for example).
To implement this object, lets call it a UserContext, which is available as a singleton. How to implement this sharedInstance can be seen here.
Once you have that, then you can add various properties to it that are global throughout the application (and by the suggestion of the name, has all global properties that belong to a particular user). One of these properties is whether the user has the app locked or not:
[[UserContext sharedInstance] isLocked] // Returns BOOL
Using this throughout your application, you can then control (at the domain concept level), whether a method can compute something or not (naturally, you'll need to make UserContext thread safe, as it could be queried anywhere at any time). It would make it clear to the developer reading the code, that a certain method can not do anything unless the user has unlocked the app. To stop
Side notes
I want that my code stops then I call [theLock lock]; and after I will call [theLock unlock]; from my UI and code will continue executing.
Do not, under any circumstances, lock the UI thread. In a published app, the watchdog will kill your app, and it will effectively crash.
ViTo, as much I concerned with the NSLock, we use it in the case of multi-threading in which we lock a particular thread and force that upto that not unlock, none other thread become active or to do his required task.
So, may be what we can do that first of all we start all of your processes in the terms of thread and at that point when you try to open your UI we call 'lock' and when user pressed the button after inputting the text-box then we call 'unlock'.
But, for this we've to sure that this thread has high priority.
That's what I'm thinking right now, but really try this with my sample code and will update you accordingly.
Check that part of code:
+(void)aMethod:(id)param{
int x;
for(x=0;x<50;++x)
{enter code here
[lock lock];
printf("Object Thread says x is %i\n",x);
usleep(1);
[lock unlock];
}
}
- (void)viewDidLoad
{
int x;
lock = [[NSLock alloc] init];
[NSThread detachNewThreadSelector:#selector(aMethod:) toTarget:[MViewController class] withObject:nil];
for(x=0;x<50;++x)
{
[lock lock];
printf("Main thread says x is %i\n",x);
usleep(10000);
printf("Main thread lets go %i\n",x);
[lock unlock];
usleep(100);
}
printf("Now getting the process");
[super viewDidLoad];
}
Check the log you'll get what you want.
Hope, it's what you need. For any concern, shout-over me.
Okay I found solution to this issue, below you can see implemented function and line by line description.
StdString ShowLockScreen()
{
// Create NSCondition lock object.
NSCondition* conditionLock = [[NSCondition alloc] init];
// Here I create my UI which must ask user to enter PIN.
PinLockController* controller = [[PinLockController alloc] initWithStyle:PinLockTypeSet];
controller.delegate = m_Context;
// Here I lock the thread but not main thread (this is very important) I start
// ShowLockScreen function in new thread and lock it.
[conditionLock lock];
dispatch_sync(dispatch_get_main_queue(), ^{
// I call function which shows my UI in main thread as UI can be shown
// only in MAIN THREAD. (This is important too.)
[controller ShowLockController:conditionLock];
});
// Then I set lock to wait, how you can see I pass conditionLock as an
// argument to ShowLockController function in that function when user
// enter his PIN and press okay button I call [conditionLock signal];
// and my code code here after wait and continue executing.
[conditionLock wait];
NSLog(#"Come here then I call [conditionLock signal]!!!")
}