Recent

Author Topic: Completion handler global var issue  (Read 242 times)

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1008
  • Former Delphi 1-7, 10.2 User
Completion handler global var issue
« 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
« Last Edit: September 19, 2020, 02:30:52 am by trev »
o Lazarus v2.1.0 r63871, FPC v3.3.1 r46876, macOS 10.14.6 (with sup update), Xcode 11.3.1
o Lazarus v2.1.0 r61574, FPC v3.3.1 r42318, FreeBSD 12.1 amd64 (VMware Fusion VM)
o FPC 3.0.4, FreeBSD 12.2-STABLE r365646 amd64
o Lazarus v2.1.0 r61574, FPC v3.0.4, Ubuntu 20.04 (Parallels VM)

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 776
Re: Completion handler global var issue
« Reply #1 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.

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1008
  • Former Delphi 1-7, 10.2 User
Re: Completion handler global var issue
« Reply #2 on: September 20, 2020, 02:59:09 am »
Thanks for the explanation (and links) Jonas.
o Lazarus v2.1.0 r63871, FPC v3.3.1 r46876, macOS 10.14.6 (with sup update), Xcode 11.3.1
o Lazarus v2.1.0 r61574, FPC v3.3.1 r42318, FreeBSD 12.1 amd64 (VMware Fusion VM)
o FPC 3.0.4, FreeBSD 12.2-STABLE r365646 amd64
o Lazarus v2.1.0 r61574, FPC v3.0.4, Ubuntu 20.04 (Parallels VM)

 

TinyPortal © 2005-2018