Are event handlers re-entrant in Embarcadero C++Builder? - c++

I'd like to ask some advice on how handle an Embarcadero CB10.1 issue with re-entrancy. Compiled in Debug configuration with "Disable all optimizations" set to true. I'm running on Win7.
I have a simple test case. A form with two buttons. The OnClick event handler for each button calls the same CPU intensive function. Below is the header file followed by the program file.
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TButton *Button1;
TButton *Button2;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
private: // User declarations
double __fastcall CPUIntensive(double ButonNo);
double __fastcall Spin(double Limit);
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Button1->Caption = "Pushed";
double retv = CPUIntensive(1);
Button1->Caption = "Button1";
if (retv) ShowMessage("Button1 Done");
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
Button2->Caption = "Pushed";
double retv = CPUIntensive(2);
Button2->Caption = "Button2";
if (retv) ShowMessage("Button2 Done");
}
//---------------------------------------------------------------------------
double __fastcall TForm1::CPUIntensive(double ButtonNo)
{
//
static bool InUse = false;
if (InUse) {
ShowMessage("Reentered by button number " + String(ButtonNo));
while (InUse) {};
}
double retv;
InUse = true;
retv = Spin(30000); // about 9 seconds on my computer
//retv += Spin(30000); // uncomment if you have a faster computer
//retv += Spin(30000);
InUse = false;
return retv;
}
//---------------------------------------------------------------------------
double __fastcall TForm1::Spin(double Limit)
{
double k;
for (double i = 0 ; i < Limit ; i++) {
for (double j = 0 ; j < Limit ; j++) {
k = i + j;
// here there can be calls to other VCL functions
Application->ProcessMessages(); // added so UI would be responsive (2nd case)
}
}
return k;
}
//---------------------------------------------------------------------------
-
1st case : the code shown but WITHOUT the call to ProcessMessages().
When I run this and click on button 1, CPU usage jumps up to almost
100% for about 9 seconds. The form becomes unresponsive during this time.
Can't move the form or click on button 2.
That works as I would expect.
2nd case : To make the form responsive to the user during the CPU
intensive function, I added the ProcessMessages() call as shown.
Now, I can move the form around and click on other buttons.
That is not always good, because I could click on button 1 again or
even click on button 2. Either click would fire off the CPU intensive function again. To prevent the CPU intensive function from running the second time, I made a static boolean flag "InUse". I set that
when the function starts and clear it when the function completes.
So I check the flag when I enter the CPU intensive function and
if its set (it must have been set by a previous click on a button), I
show a message and then wait for the flag to clear.
But the flag never clears and my program loops on the 'while' statement
forever. I would like the program to just wait for the CPU intensive function
to complete and then just run it again.
If I set a breakpoint in the Spin() function after I hit the deadlock,
it never fires indicating that neither event is executing.
I know the VCL is not thread safe but here, all of the processing takes
place in the main thread. In my actual code, there are many calls to
VCL functions so the CPU intensive function has to remain in the main
thread.
I considered Critical Sections and Mutexes but since everything is in
the main thread, any use of them does no blocking.
Maybe its a stack issue? Is there a solution that lets me handle this without the deadlock?

2nd case : To make the form responsive to the user during the CPU intensive function, I added the ProcessMessages() call as shown. Now, I can move the form around and click on other buttons.
That is always the wrong solution. The correct way to handle this situation is to move the CPU intensive code to a separate worker thread, and then have your button events start a new instance of that thread if it is not already running. Or, keep the thread running in a loop that sleeps when it doesn't have work to do, and then have each button event signal the thread to wake up and do its work. Either way, NEVER block the main UI thread!
That is not always good, because I could click on button 1 again or even click on button 2. Either click would fire off the CPU intensive function again.
To prevent the CPU intensive function from running the second time, I made a static boolean flag "InUse". I set that when the function starts and clear it when the function completes.
A better way would be to disable the buttons while the work is being performed, and re-enable them when finished. Then the work can't be re-entered to begin with.
But, even if you keep your flag, your function should just exit without doing anything if the flag is already set.
Either way, you should display a UI displayed telling the user when the work is in progress. This becomes easier to manage if the work is done in a separate thread.
So I check the flag when I enter the CPU intensive function and if its set (it must have been set by a previous click on a button), I show a message and then wait for the flag to clear.
But the flag never clears and
That is because you are just running an endless loop that does nothing, so it doesn't allow the code to progress any further. And certainly not finish the existing work and reset the flag.
The smallest fix you can make to your existing code without re-writing it is to change CPUIntensive() to use return 0 instead of while (InUse) {} when InUse is true. That will allow a call to ProcessMessages() to exit and return control back to the previous CPUIntensive() call that is waiting to finish running.
I know the VCL is not thread safe but here, all of the processing takes place in the main thread.
Thay is a BIG mistake.
In my actual code, there are many calls to VCL functions so the CPU intensive function has to remain in the main thread.
That is not a good enough reason to perform the work in the main thread. Move it to a worker thread, where it belongs, and have it sync with the main thread whenever it needs to access the UI. Do as much work as possible in the worker thread, and sync only when absolutely necessary.

My question was not about threads but rather how to prevent multiple clicks of buttons from being acted upon while at the same time, not having the form become unresponsive. All of this in my single threaded VCL program. As I saw, when I did not have the call to ProcessMessages(), the form became unresponsive once a button was clicked (until the event handler completed its processing). When I added the call to ProcessMessages(), the form was TOO responsive in that mouse clicks caused event handlers to run EVEN IF the same mouse click's event handler was only part way complete when it called ProcessMessages(). The event handlers are not re-entrant but Windows/VCL was re-entering them when the second mouse button was pushed.
I needed a way to defer processing of mouse button events while at the same time processing messages so the form did not appear unresponsive.
ProcessMessages() was not going to work here. It dispatched every message that it found in the message queue.
I found a way to go part way, a version of ProcessMessages that checked the message queue and if a non-mouse button message was there, dispatch it. Otherwise, leave the messsage in the queue for later.
Here is the code I ended up with to replace the call to ProcessMessages:
// set dwDelay to handle the case where no messages show up
MSG msg;
DWORD dwWait = MsgWaitForMultipleObjects(0, NULL, FALSE, dwDelay, QS_ALLINPUT);
if (dwWait == WAIT_TIMEOUT) { // Timed out?
// put code here to handle Timeout
return;
}
// Pump the message queue for all messages except Mouse button messages
// from 513 to 521 (0x0201 to 0x0209)
bool MsgAvailable;
while (true) {
MsgAvailable = PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
if (!MsgAvailable) break; // no messages available
if (msg.message <= WM_MOUSEMOVE) {
// Message from WM_NULL to and including WM_MOUSEMOVE
GetMessage(&msg, NULL, WM_NULL, WM_MOUSEMOVE);
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
if (msg.message >= (WM_MOUSELAST+1)) {
// Message from WM_MOUSELAST+1 to the last message possible
GetMessage(&msg, NULL, WM_MOUSELAST+1, 0xFFFFFFFF);
TranslateMessage(&msg);
DispatchMessage(&msg);
continue;
}
// if all that's left is mouse button messages, get out
if (msg.message > WM_MOUSEMOVE || msg.message < WM_MOUSELAST+1) break;
}
return;
Now the event handler gets to finish its processing without re-entry. All of the non-mouse button events get processed. When the event handler is done, control goes back to the main VCL thread message pump and the waiting mouse button event(s) is/are fired.

Related

QT: Run a function as long as button is toggled

I want to implement a GUI that receives messages from an external device. The "advancedReceiveExample" is waiting for messages. Once it has received one, it does stuff with it, saves it and terminates.
I want to make my function wait for new messages after receiving one as long as the button is toggled.
I have tried this so far:
void MainWindow::on_pushButton_clicked()
{
if (ui.pushButton->isChecked()) {
ui.pushButton->setText("Stop Receiving");
ui.label_3->setText("Receiving...");
advancedReceiveExample(ui.comboBox->currentIndex() + 1);
}
else
{
ui.pushButton->setText("Start Receiving");
ui.label_3->setText("Not Receiving");
}
}
This works perfectly fine but as mentioned above it only receives one message. If I do that:
void MainWindow::on_pushButton_clicked()
{
if (ui.pushButton->isChecked()) {
ui.pushButton->setText("Stop Receiving");
ui.label_3->setText("Receiving...");
while (1)
{
advancedReceiveExample(ui.comboBox->currentIndex() + 1);
}
}
else
{
ui.pushButton->setText("Start Receiving");
ui.label_3->setText("Not Receiving");
}
}
it blocks the function because the state of the button can only be change after the function "on_pushButton_clicked()" has terminated.
Visual Studio 2019
C/C++
EDIT: Okay, I have understood the problem of blocking the thread. Multithreading might be the right option but I am very unexperienced regarding this topic. The <QThread> could be possible. How would you use it?
Do you have suggestions which other library could be used?
Note QT is event-based. If you keep your computer busy inside some function without returning to the main loop frequently, your GUI will freeze.
What you need to do is slice your action that you want to do into small bits that can repeatedly return to the main loop in order to keep the GUI responsive. (Another method yould be to swap out your action into a separate thread and handle it in parallel, killing the thread when the button is released)
Probably the simplest method to do what you want is with timers that you arm in the PushButton::clicked slot, and then check in the timer event whether the button is still pressed, and, if yes, do a bit of your action, save state and re-arm the timer to have you return.
Something along the lines of the following pseudo code should work and execute what you want to do in slices every 10ms:
MainWindow::onPushButtonClicked () {
// do the action, or, alternatively, start a
// parallel thread that does it
do_a_bit_of_action();
// sets up a timer to call onTimer after 10ms
QTimer::singleShot (10, this, SLOT(onTimer()));
}
MainWindow::onTimer () {
// check if button is still held down
if (pushButton.down) {
// re-arm timer
Timer::singleShot (10, this, SLOT(onTimer()));
// do some more action bits
do_a_bit_of_action();
}
else {
// kill optional background thread here
}
}
You can try it with:
while(ui.pushButton->isChecked()){
*your function*
}

Performance when use a timer vs a lot of thread to listen event changed?

I need listen a lot of (<10) external event send to app and process them. Event can happen every 50ms or can is a hour, can't predetermine time or frequency, depend user. System use pthread on linux 3.6.5, single core cpu, ram 512. Listener must start at begin system and stop at end system, don't delay recive event (in 50ms). Moreover, also have a thread run update UI, 2 thread in threadpool to download.
External event here can is mouse click, keyboard key down/up, on/off LCD, button power, press key ir remote, a file modified, a alarm push by server,..
I consider 2 option, a listener on thread or a timer thread.
can any one please explain efficient of performance with both above away when use on descripted system ? and which one would be a better choise or a new option ?
a listener on a thread
//==================================== option 1: use 1 listener/thread
// i = [0, n]
bool waitForEvent_i(){
// can is poll change on a file description, read on socket
// or pthread_cond_wait a other thread
// ...
}
void thread_i(){
while(waitForEvent_i()){
excute_i();
}
}
void startListener(){
startThread_0();
startThread_1();
....
startThread_n(); // n < 10;
}
a pthread such as timer proactive check all event can
//================================== option2: use timer to interval check
class Task{
public:
void run(){
// check if have change, call excute_i()
}
};
void timer_thread(timeout){
while(1){
while(!queue.empty()}
{
task = queue->getTask();
task->run();
usleep(timeout - task->timeExcuted()); // suppose, timeExcuted < timeout
}
usleep(timeout);
}
}
void startTimer(){
start_Timer_thread();
}

gtk_widget_add_tick_callback() and gtk_main_iteration()

I have two GTK windows
Normal (main) window that runs animation, draws stuff in callback registered by gtk_widget_add_tick_callback().
At some point secondary window is created that runs modal loop:
void show_modal()
{
GtkWindow* gw = gtkwindow(this);
if( parent() )
gtk_window_set_transient_for(gw, gtkwindow( parent() ));
gtk_widget_show(GTK_WIDGET(gw));
gtk_window_set_modal(gw,TRUE);
gtk_window_set_keep_above(gw,TRUE);
this->update_window_state(gool::WINDOW_SHOWN);
while( this->is_valid_window() )
{
if(this->_window_state == WINDOW_HIDDEN) break;
if(this->_window_state == WINDOW_STATE_NA) break;
gtk_main_iteration(); // gtk_main_iteration_do(true);
}
}
Problem: Animation in main window works fine until show_modal() is invoked. It appears as gtk_main_iteration(); blocks ticks added by gtk_widget_add_tick_callback() function. As soon as I close secondary window and so while() {gtk_main_iteration();} loop exits then animations in main window start running again.
Any idea of how to make "animation friendly" modal loops in GTK?
UPDATE: it appears as gtk_main_iteration(); blocks not only ticks but any updates of any windows other than "current" - they are simply frozen. What is the reasoning of such GTK behavior?
UPDATE #2:
gtk_dialog_run(); behaves exactly as gtk_main_iteration(); - locks any updates on any window in process other than active window.
It seems to be by definition: link
gboolean gtk_main_iteration (void);
Runs a single iteration of the mainloop. If no events are waiting to be processed GTK+ will block until the next event is noticed. If you don’t want to block look at gtk_main_iteration_do() or check if any events are pending with gtk_events_pending() first.
The explanation suggests to use gtk_main_iteration_do(FALSE) if you don't want blocking:
gboolean gtk_main_iteration_do (gboolean blocking);
Runs a single iteration of the mainloop. If no events are available either return or block depending on the value of blocking:
TRUE if you want GTK+ to block if no events are pending
As for gtk_dialog_run: it also blocks by design link
gint gtk_dialog_run (GtkDialog *dialog);
Blocks in a recursive main loop until the dialog either emits the “response” signal, or is destroyed.[...]
I read about people solving this using multiple threads: handle the GUI in the main thread and do background work in another one. There's an article about it here that might be useful.
I assume that show_modal is called from a callback or other activity in main context. You could try adding your modal window into main context using invoke or signal_idle.
This way execution of show_modal will end.
#include <gtkmm.h>
#include <string>
int main()
{
auto Application = Gtk::Application::create();
Gtk::Window window;
Gtk::Window* window2;
Gtk::Button button;
window.add(button);
//I hope timeout behaves similar to ticks. I have no idea how animations in GTK work
int i=0;
Glib::MainContext::get_default()->signal_timeout().connect([&]()->bool{
button.set_label(std::to_string(i++));
return true;
}, 1000);
button.signal_clicked().connect([&]{
Glib::MainContext::get_default()->invoke([&]()->bool{
window2 = new Gtk::Window;
window2->set_modal(true);
window2->set_keep_above(true);
window2->signal_delete_event().connect([&](GdkEventAny* any_event)->bool{
delete window2;
return false;
});
window2->show_all();
return false;
});
});
window.show_all();
return Application->run(window);
}

C++ How can i trigger that a PostMessage was proceed in another thread

I have a MFC-C++ application where at least two threads are running "MainFrame" (=GUI thread) and a "Solver" thread.
At one point the second thread (Solver) initiate a change in the model which the GUI thread should execute by a PostMessage(...). To be safe I want to wait that message was proceeded to continue in the second thread.
By using a SendMessage(...) the Solver thread waits for the message to be executed but in this way we bypass the message queue which shouldn't be the goal.
My question: How can I properly and clean check/trigger that my message was proceed before I continue?
Did we need to check every 'x' seconds the status of the main thread message queue by GetQueueStatus(...) ?
Is there a way to have the main thread send back a "success event" to the other thread? And that the second one waits to have an event back?
Did boost provide an easy solution for this kind of problems?
Was there already a similar question which i didn't found? (sorry)
My function:
void PostSequencerMessageToGUI(ESequencerSignal signal, CSchedulerStep * step)
{
CMainFrame *mainFrame = theApp.GetMainFrame();
assert(mainFrame);
if (!mainFrame)
return;
mainFrame->PostMessage(WM_SEQUENCER_SIGNAL, signal, reinterpret_cast<LPARAM>(step));
// mainFrame->SendMessage(WM_SEQUENCER_SIGNAL, signal, reinterpret_cast<LPARAM>(step));
// Message was posted, now wait for event back to continue procedure
// ... but how? ...and when to cancel ? ...
return;
}
As SendMessage is ignoring the current message queue (it pass the queue) i couldn't use this approach.
I found my solution in another question where it is solved using a Condition variables and a Mutex.
https://stackoverflow.com/a/16909012/5036139
My solution:
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
boost::condition_variable g_sequencerJobCondition;
boost::mutex g_guiMutex;
void PostSequencerMessageToGUI(ESequencerSignal signal, CSchedulerStep * step)
{
CMainFrame *mainFrame = theApp.GetMainFrame();
assert(mainFrame);
if (!mainFrame)
return;
bool work_is_done = false;
try {
boost::mutex::scoped_lock lock(g_guiMutex);
mainFrame->PostMessage(WM_SEQUENCER_SIGNAL, reinterpret_cast<WPARAM>(&work_is_done), reinterpret_cast<LPARAM>(step));
// Message was posted, now wait for event back to continue procedure
while (!work_is_done){
g_sequencerJobCondition.wait(lock);
}
}
catch (... /*e*/){
// Handle all kind of exception like boost::thread_resource_error, boost::thread_interrupted, boost::exception, std::exception
// ...
}
// ...
return;
}
And
LRESULT CMainFrame::OnSequencerPostMessage( WPARAM wParam, LPARAM lParam )
{
// ...
bool *work_is_done = reinterpret_cast<bool*>(wParam);
CSchedulerStep* step = reinterpret_cast<CSchedulerStep*>(lParam);
// Handle business case ...
// ...
// Finally notify sequencer thread that the work is done
work_is_done = true;
g_sequencerJobCondition.notify_one();
return true;
}

How to prevent a long process to hangs wxwidgets window

I have a wxwindows application and in the onclick event of a button, I have a very long process, for example I have something such as this:
for(int i=1;i<100;i++)
{
sleep(1000);
gaugeProgress->SetValue(i);
*textOutput<<i;
}
Running this code, stops UI to be responsive. I add
Refresh();
Update();
just after
*textOutput<<i;
but it did not work.
is there any way that I can pump the events?
I am working on Windows using VS 20102
In those cases I use wxYield() like this:
for(int i = 1; i < 100; i++)
{
// sleep() freezes the program making it unresponsible.
// sleep(1000);
gaugeProgress->SetValue(i);
*textOutput << i;
// wxYield stops this function execution
// to process all the rest of stocked events
// including the paint event and resumes immediately.
wxYield();
}
This stops the current process and lets the application to process the message stack like the paint event.
But I think that the proper way to do this should be using threads.
You can add a wxTimer member in your wxwindows, start it in the window constructor, as such:
m_timer.Start(1000);
then capture the timer event with a function, for example:
void mywindow::OnTimer(wxTimerEvent& event)
{
Refresh();
Update();
}
Make sure you connect the event to the wxTimer member.