C builder RAD 2010 RTL/VCL Application->Terminate() Function NOT TERMINATING THE APPLICATION - c++builder

I have a problem also described here: http://www.delphigroups.info/3/9/106748.html
I have tried almost all forms of placing Application->Terminate() func everywhere in the code, following and not 'return 0', 'ExitProcess(0)', 'ExitThread(0)', exit(0). No working variant closes the app. Instead the code after Application->Terminate() statement is running.
I have two or more threads in the app. I tried calling terminate func in created after execution threads and in main thread.
Also this is not related (as far as I can imagine) with CodeGuard / madExcept (I have turned it off and on, no effect). CodeGuard turning also did not do success.
The only working code variant is to place Application->Terminate() call to any of any form button's OnClick handler. But this does not fit in my needs. I need to terminate in any place.
What I should do to terminate all the threads in C++ Builder 2010 application and then terminate the process?

Application->Terminate() does not close application immediately, it only signals you want to close the application.
Terminate calls the Windows API
PostQuitMessage function to perform an
orderly shutdown of the application.
Terminate is not immediate.
In your functions call Application->ProcessMessages() then check if the Application->Terminated property is true.
For applications using
calculation-intensive loops, call
ProcessMessages periodically, and
also check Terminated to determine
whether to abort the calculation and
allow the application to terminate
For example:
void Calc()
{
for (int x = 0; x < 1000000; ++x)
{
// perform complex calculation
// check if need to exit
Application->ProcessMessages();
if (Application->Terminated)
{
break;
} // end if
} // end for
// clean up
}

Related

How to pass native void pointers to a Dart Isolate - without copying?

I am working on exposing an audio library (C library) for Dart. To trigger the audio engine, it requires a few initializations steps (non blocking for UI), then audio processing is triggered with a perform function, which is blocking (audio processing is a heavy task). That is why I came to read about Dart isolates.
My first thought was that I only needed to call the performance method in the isolate, but it doesn't seem possible, since the perform function takes the engine state as first argument - this engine state is an opaque pointer ( Pointer in dart:ffi ). When trying to pass engine state to a new isolate with compute function, Dart VM returns an error - it cannot pass C pointers to an isolate.
I could not find a way to pass this data to the isolate, I assume this is due to the separate memory of main isolate and the one I'm creating.
So, I should probably manage the entire engine state in the isolate which means :
Create the engine state
Initialize it with some options (strings)
trigger the perform function
control audio at runtime
I couldn't find any example on how to perform this actions in the isolate, but triggered from main thread/isolate. Neither on how to manage isolate memory (keep the engine state, and use it). Of course I could do
Here is a non-isolated example of what I want to do :
Pointer<Void> engineState = createEngineState();
initEngine(engineState, parametersString);
startEngine(engineState);
perform(engineState);
And at runtime, triggered by UI actions (like slider value changed, or button clicked) :
setEngineControl(engineState, valueToSet);
double controleValue = getEngineControl(engineState);
The engine state could be encapsulated in a class, I don't think it really matters here.
Whether it is a class or an opaque datatype, I can't find how to manage and keep this state, and perform triggers from main thread (processed in isolate). Any idea ?
In advance, thanks.
PS: I notice, while writing, that my question/explaination may not be precise, I have to say I'm a bit lost here, since I never used Dart Isolates. Please tell me if some information is missing.
EDIT April 24th :
It seems to be working with creating and managing object state inside the Isolate. But the main problem isn't solved. Because the perform method is actually blocking while it is not completed, there is no way to still receive messages in the isolate.
An option I thought first was to use the performBlock method, which only performs a block of audio samples. Like this :
while(performBlock(engineState)) {
// listen messages, and do something
}
But this doesn't seem to work, process is still blocked until audio performance finishes. Even if this loop is called in an async method in the isolate, it blocks, and no message are read.
I now think about the possibility to pass the Pointer<Void> managed in main isolate to another, that would then be the worker (for perform method only), and then be able to trigger some control methods from main isolate.
The isolate Dart package provides a registry sub library to manage some shared memory. But it is still impossible to pass void pointer between isolates.
[ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: Invalid argument(s): Native objects (from dart:ffi) such as Pointers and Structs cannot be passed between isolates.
Has anyone already met this kind of situation ?
It is possible to get an address which this Pointer points to as a number and construct a new Pointer from this address (see Pointer.address and Pointer.fromAddress()). Since numbers can freely be passed between isolates, this can be used to pass native pointers between them.
In your case that could be done, for example, like this (I used Flutter's compute to make the example a bit simpler but that would apparently work with explicitly using Send/ReceivePorts as well)
// Callback to be used in a backround isolate.
// Returns address of the new engine.
int initEngine(String parameters) {
Pointer<Void> engineState = createEngineState();
initEngine(engineState, parameters);
startEngine(engineState);
return engineState.address;
}
// Callback to be used in a backround isolate.
// Does whichever processing is needed using the given engine.
void processWithEngine(int engineStateAddress) {
final engineState = Pointer<Void>.fromAddress(engineStateAddress);
process(engineState);
}
void main() {
// Initialize the engine in a background isolate.
final address = compute(initEngine, "parameters");
final engineState = Pointer<Void>.fromAddress(address);
// Do some heavy computation in a background isolate using the engine.
compute(processWithEngine, engineState.address);
}
I ended up doing the processing of callbacks inside the audio loop itself.
while(performAudio())
{
tasks.forEach((String key, List<int> value) {
double val = getCallback(key);
value.forEach((int element) {
callbackPort.send([element, val]);
});
});
}
Where the 'val' is the thing you want to send to callback. The list of int 'value' is a list of callback index.
Let's say you audio loop performs with vector size of 512 samples, you will be able to pass your callbacks after every 512 audio samples are processed, which means 48000 / 512 times per second (assuming you sample rate is 48000). This method is not the best one but it works, I still have to see if it works in very intensive processing context though. Here, it has been thought for realtime audio, but it could work the same for audio rendering.
You can see the full code here : https://framagit.org/johannphilippe/csounddart/-/blob/master/lib/csoundnative.dart

MQL Program unexpectedly terminated

I'm new to MQL language, so please correct me if I described something wrong.
I made an script by the script editor to place orders automatically. The program should be never stopped unless by manually termination. My code looks like that:
void onStart()
{
While(true)
{
Sleep(10000);
MakeOrder(....);//of course actual code is much more complicated
}
}
The only preset functions I use are trade functions, math functions and time functions.
The code works well for most of the times that can continue running at least for 48 hours, but sometimes it might unexpectedly stopped reporting deinit reason 4(which is the same exit code if I click stop button when debugging) within one hour after starting. It looks that MQL doesn't have try...catch module, and getting error in some coding lines won't stop it. I wonder what might have happened behind the termination? Or how can I ignore it, so at least the program can automatically restart?
You should check the OnTimer and OnTick functions.
And recommended to use IsStopped() in the While loop.
void onStart()
{
while(!IsStopped())
{
Sleep(10000);
MakeOrder(....);//of course actual code is much more complicated
}
}
Uninitialization Reason 4 is : chart has been closed. In MT4, you always need to run a script on a chart (window), so of course if this chart is close for any reason, your script will terminate. There is nothing you can do to prevent that.
As suggested, adding IsStopped() will terminate your loop (and script), so what you can do is to add some code after your loop to notify you the script is being terminated.
For example :
void OnStart()
{
//---
while(!IsStopped())
{
Sleep(10000);
//MakeOrder(....);//of course actual code is much more complicated
}
//---
if(UninitializeReason()==REASON_CHARTCLOSE)
{
string msg="Chart is closed and the script is terminated.";
Alert(msg);
SendNotification(msg);
}
}

Delphi - Recompiling application with 10.2.1 causes memory leaks?

I just installed Delphi 10.2 Release 1. When I recompiled my applications and ran them, I get a lot of memory leaks. I had no memory leaks with 10.2 (without the update). I made no changes to the code either.
To verify, I created a simple blank application and put a few components on the form. No code. Ran the application and got memory leaks reported.
I wanted to highlight this (if only as a warning before you upgrade).
My questions:
Has anyone else seen this issue?
Is there something I need to or could be doing to get rid of this issue?
Note: I have logged an issue on quality portal, just in case this is a real issue: https://quality.embarcadero.com/browse/RSP-18774. In this ticket I have also attached the sample app.
After some investigation I found out that the callbacks being passed to TThread.CurrentThread.ForceQueue in TStyledControl.KillResourceLink are never executed because before any thread can handle them the application is ending and the TThread class destructor is destroying the list that still has unhandled callbacks.
I solved this by adding a call to CheckSynchronize at the end of FMX.Forms.DoneApplication which forces the callbacks to be executed which resolved the huge memory leak.
I don't know if this is the correct fix for the issue but it solved the memory leaks being reported.
I have the same problem using C++Builder 10.2.1 in FMX and in VCL applications.
If I enable CodeGuard, I get memory leaks on application exit.
I have a TThread with OnTerminate handler: if I put a breakpoint in this handler, when I close the program it is never called.
If I put CheckSynchronize() in the destructor of my main application form, the problem remains.
My solution was a "horrible" loop like this in the destructor of the main form:
__fastcall TForm3::~TForm3(void) {
for(int i = 0; i < 10; i++) {
Sleep(1);
CheckSynchronize();
}
}
This solution is not deterministic but may be used in your application in debug mode to avoid CodeGuard error messages.
Another solution is using the WaitFor() function if MyThread is a TThread object:
MyThread = new MyThreadClass();
and DeleteThisTh() is a method of this class, we can wait for terminated thread inside DeleteThisTh():
void MyThreadClass::DeleteThisTh(void) {
Terminate();
WaitFor();
delete this;
}
In the OnTerminate event, I can clean my objects. Take note:
delete this is called after OnTerminate;
DeleteThisTh() lives in the main thread;

How to terminate a long running isolate #2

I am trying to understand how I shall port my Java chess engine to dart.
So I have understood that I should use an Isolates to run my engine in parallell with the GUI but how can I force the engine to terminate the search.
In java I just set some boolean that where shared between the engine thread and the gui thread.
Answer I got:
You should send a message to the isolate, telling it to stop. You can simply do something like:
port.send('STOP');
My request
Thanks for the clarification. What I don't understand is that if the chess engine isolate is busy due to a port.send('THINK') command how can it respond to a port.send('STOP') command
Each isolate is single-threaded. As long as your program is running nobody else will have the means to interfere with your execution.
If you want to be able to react to outside events (including messages from other isolates) you need to split your long running execution into smaller parts. A chess-engine probably has already some state to know where to look for the next move (assuming it's built with something like A*). In this case you could just periodically interrupt your execution and resume after a minimal timeout.
Example:
var state;
var stopwatch = new Stopwatch()..run();
void longRunning() {
while (true) {
doSomeWorkThatUpdatesTheState();
if (stopwatch.elapsedMilliseconds > 200) {
stopwatch.reset();
Timer.run(longRunning);
return;
}
}
}
The new API will contain a
isolate.kill(loopForever ? Isolate.IMMEDIATE : Isolate.AS_EVENT);
See https://code.google.com/p/dart/issues/detail?id=21189#c4 for a full example.

How to start a thread into a service in delphi 7, Windows XP?

We need to Start a thread into a service application we developed.
We did in the OnExecute event, and it failed, and later we did in the OnStart event, and it failed again. Maybe we have to do something else to start the thread.
The line of code we only have to type is MonitorThread.Start;
Where and how we can to start the thread??
Thanks.
On the face of it, starting a thread in a service is no different from starting a thread in any other kind of application. Simply instantiate the thread object and let it run. If you created the object in a suspended state, then call Start on it (or, in versions earlier than 2010, Resume).
MonitorThread := TMonitorThread.Create;
MonitorThread.Start; // or MonitorThread.Resume
If that doesn't work, then you need to take a closer look at exactly what doesn't work. Examine exception messages and return codes. Use the debugger to narrow things down.
If it's possible, I advise you to not create the thread suspended. Instead, just provide the object all the parameters it needs in its constructor. Let it initialize itself, and it will start running just before the constructor returns to the caller. No need for additional thread management outside the thread object.

Resources