put URL

Mark Waddingham mark at livecode.com
Tue Sep 22 08:42:03 EDT 2015


On 2015-09-18 20:44, Richard Gaskin wrote:
> Peter Haworth wrote:
>> The dictionary says all actions that refer to a URL are blocking but 
>> if I
>> execute:
>> 
>> put URL myURL into tResults
>> 
>> ... my handler immediately goes to the next statement and tResuls 
>> contains
>> "error URL is currently loading".
>> 
>> The url is question is to an api so I guess the error could be coming 
>> from
>> there but all the error messages I've received have been wrapped in 
>> XML.

No - that error is definitely coming from libURL.

> We really need some clarity on this.  I've been using LC for years,
> but whatever rules might allow me to anticipate whether network I/O is
> blocking or non-blocking have eluded me in practice.

It is somewhat subtle - there are actually three different potential 
behaviors here:

   1) Blocking without message dispatch - a command will not return until 
the operation is complete and will ensure that no messages are sent 
whilst the operation completes (equiv. to doing a wait without messages)

   2) Blocking with message dispatch - a command will not return until 
the operation is complete but will allow messages to be sent (equiv. to 
doing a wait with messages)

   3) Non-blocking - a command will return immediately and not cause any 
sort of wait.

All of libURLs functions which block do so with message dispatch - they 
have to as libURL is written in LiveCode Script and needs messages from 
sockets to function.

Herein lies the problem. If you do evaluate a remote URL chunk (e.g. url 
"http://livecode.com), whilst the evaluation will not return until it 
has the data, it is still possible for your scripts to get messages 
whilst it is happening. Now, as it stands, libURL will only allow a 
single connection to a given server at once (IIRC) so Peter's problem is 
that whilst the URL operation is happening, his scripts are receiving a 
message which is causing the same or similar URL to be fetched - the 
calls are becoming nested (this is what you would call a re-entrancy 
problem) and thus libURL is saying 'no' to the subsequent request.

This is the only way things can really work with a feature such as 
blocking URL evaluation written in script with way the engine currently 
works - 'wait with messages nest' rather than being side-by-side.

> These days I almost always rely on callbacks, since I know those are
> always non-blocking, though even then I'm not sure of the implications
> in terms of overall performance, given that it provides us the
> illusion of concurrency but without true parallelism.

I'm not sure that is a concern here. The kernel is definitely concurrent 
in its handling of sockets and the flow of data. Thus all the app is 
doing is responding to notifications from the kernel when sockets have 
changed state in some way. For sanity of app writing (and many other 
reasons!), this is much better serialized than happening 'truly 
concurrently' - particularly as most modern OSes do not do truly 
concurrent UI manipulations.

(This is not to say that being able to offload long running computations 
/ processes onto background threads would not be useful - just limited 
in utility particularly if you want to not go slightly mad trying to 
debug things).

> Could someone on the core team draft a page that would help us
> understand network I/O in terms of blocking and non-blocking, and how
> non-blocking code is handled in a single-threaded engine?

As I said above, the fact the engine 'single-threaded' (from the point 
of view of script at least) isn't really important. The engine is almost 
a node.js model but not quite. This model is where you can fire off 
background processes which could be truly parallel but the management of 
them (in terms of state changes, dispatch, closure) always happens on 
the main thread. If you look at the development of node.js then it 
achieves exceptionally high throughput at a great deal more ease than 
previous attempts to leverage true multi-threading.

Whilst it is easy to think that 'going multi-threaded' would always be 
of benefit - in reality it rarely is. As soon as you have multiple 
things running simultaneously and wanting to communicate in some 
fashion, or access the same resources, you need locks. As soon as you 
need locks you start to, very quickly, lose the benefit of parallelism 
in the first place. We had just this experience with our attempts to 
parallelize rendering - initially it looked like it was a win-win 
situation, but it ended up being pointless as the number of points at 
which the multiple threads had to wait on locks to ensure consistency 
meant that any benefit in performance was lost.

Using multiple threads is only *really* beneficial when you can divide 
your apps actions up into (long running) bite-sized pieces of 
computation which need not interact with anything else at all whilst 
running.

Mark.

-- 
Mark Waddingham ~ mark at livecode.com ~ http://www.livecode.com/
LiveCode: Everyone can create apps




More information about the Use-livecode mailing list