Lazarus

Programming => Operating Systems => macOS / Mac OS X => Topic started by: trev on September 18, 2020, 03:49:23 pm

Title: Completion handler global var issue
Post by: trev on September 18, 2020, 03:49:23 pm
I setup an NSURLSession with code to:
* create a configuration object and a session based on that object
* a completion handler

It works, sort of. I assign the NSdata and NSresponse to global string variables because I can't eg run ShowMessage in the completion handler because it is not running in the main thread. NSLogging shows the NSdata, NSresponse, NSerror (if there is one) and global variables to which those are assigned all contain the correct content.

But, when I use ShowMessage to display the global variables, the first one (no matter which one I show first) always contains the data with which I initialised the global variable ('default') when it was declared.

I've worked around the issue with:

Code: Pascal  [Select][+][-]
  1.   while((webData = 'default')) AND (webError = 'default') do
  2.     Sleep(50);
  3.  
  4.   // display results
  5.   if(webErrorReason <> '') then
  6.     begin
  7.       ShowMessage(webError);
  8.       ShowMessage(webErrorReason);
  9.     end
  10.   else
  11.     begin
  12.       ShowMessage('Data: ' + LineEnding + webData);
  13.       ShowMessage('Response: ' + LineEnding + webResponse);
  14.       ShowMessage('Web page: ' + LineEnding + webHTML);
  15.     end;

but I don't understand why the issue exists in the first place.

[EDIT]Better work around
Title: Re: Completion handler global var issue
Post by: Jonas Maebe on September 19, 2020, 04:17:32 pm
When code in thread A modifies data used by code in thread B, you must always insert synchronisation operations between the two threads, or they may see memory operations happen out of order. See e.g. https://www.kernel.org/doc/Documentation/memory-barriers.txt for a fairly extensive explanation of the issues (no need to read all the way to the end).

The simplest and safest way to synchronise between the two threads is by setting an RTLEvent in the thread once it finishes (your completion handler), and waiting for that RTLEvent in the thread that waits for the completion. See https://www.freepascal.org/docs-html/rtl/system/rtleventsetevent.html and related procedures.
Title: Re: Completion handler global var issue
Post by: trev on September 20, 2020, 02:59:09 am
Thanks for the explanation (and links) Jonas.
TinyPortal © 2005-2018