@bogs: Richard has probably been using Jacque's time machine stack for years... However, probably incorrectly which is why he still doesn't word things well
... without the clues you'd pick up in person (although I've seen that fail pretty badly as well).
Hehe - tell me about it!
Anyways, I'll give it a shot, just don't expect it to be coherent. Or Shakespear. I also hate to bring up other languages, but my disjointed understanding of this one means I may not have the right words otherwise.
Heh - there's never an issue (in my mind at least) with cross comparisons with other languages - a programming language can't be developed in isolation. There's a long history in programming language design of borrowing, adapting and sometimes just blatantly stealing notions from existing ones; on the flip side it also helps determine what things are generally just a really bad idea!
So - yes - RB/Delph. I have played with RB a bit (years and years ago - in the late 90's I think) its what you expect very similar to VB pre .NET (although admittedly mostly because of its 'traditional' BASIC heritage). So it kind does / works / is really just like that... Just a cross-platform version these days!
Delphi I loved. I quite liked how they mutated Pascal, subtlety, into something which allowed components to be built and then tied together in a very natural way and which fit so well with Window's underlying concepts (I mean, the fact it was a single declaration to wrap an API / COM call and have any errors massaged into an exception was pretty cool in its own right!).
One thing to remember is that Delphi, in particular, was a Windows thing. There aim was not cross-platform - it was to enable people to write Window's software much more easily using all the ideas and notions about such which existed at the time - but in an easier way. They essentially took MFC / ATL (MS's C/C++ based App building frameworks), improved them, wrapped them in explicit syntax in the language so as to eliminate a lot of the cruft you needed to do the same thing in C++ - then bound together a Form-designed based IDE and the ability to easily create independent components which could be shared.
Due to its single platform nature - it meant that things like threading and everything else could be implemented in the way the OS allowed. Out of the 'big 5' OSes which are the main ones which are around today - Windows, Mac, Linux, iOS and Android... Windows stands in a separate class. The other four are all UNIX derived - Windows is not UNIX. It is nothing like UNIX at all in fact. MS created their own entire thing there - whose architecture is fundamentally different from the others. (For better or for worse - I do think 'worse' these days - I don't think I always did).
On Windows UI and Kernel are essentially intertwined - this means threading is more portable amongst threads and as such there's various things you can do on Windows, which you cannot on the other platforms.
So, anyway, sorry for the digression - but - yes - Delphi had true pre-emptive threading. It could do that, in its UI, and across the board - because Windows - at the UI API level could relatively easily. Okay, so yes, you still have to be careful with locks and so forth. However, because Windows handled UI events in a certain way, and tied threads to actual windows in a certain way, and a littany of other things. It worked, it was relatively straightforward, and it worked.
In terms of your question about blocking and non-blocking...
A non-blocking call is one where you initiate the call - and then you ask it to tell you when it is done - in LC terms you get a callback message.
A blocking call is one where you initiate the call, but then nothing else happens until it is completed.
All non-blocking calls can be made blocking with a little bit of scripting:
Code: Select all
local sCallResult
on blockingCall
put empty into sCallResult
nonBlockingCall "callMeBack"
wait until sCallResult is not empty with messages
return sCallResult
end blockingCall
on callMeBack pNonBlockingResult
put pNonBlockingResult into sCallResult
end callMeBack
Whether things are better as blocking or non-blocking largely depends on what you are doing.
If something is essentially a 'bit of work which needs to be done, but won't interfere with the users use of a program until it is complete' - then non-blocking is ideal.
On the other hand, if something is 'a bit of work which is required for the user to be able to take the next step' - then blocking is ideal.
In a model where wait is not recursive (which is not currently the case in LiveCode) - then there isn't actually any difference between the two. You can always use blocking - you just have to remember to take into account that other things (which you initiate) might be happening whilst one call is waiting for completion (although you have to do that in the non-blocking model too). Essentially if wait is non-recursive then you don't have to split up a series of blocking handler calls into lots of little handlers tied together 'with message' to make them non-blocking - they just are... Should you want them to be.
In terms of threading - there are two factors in terms of my general 'anti-general-threading'.
The first is purely related to LiveCode code base. It is old, it is large - it was, quite frankly, poorly architected from the start (I have spent a great deal of time and effort trying to improve that!). It was also designed and built for old-style UNIX platforms without any regard for it ever being cross-platform (the UNIXy design goes right down to the core architecture such that it ever had!). Cleaving in multi-threading in any full generality now would be *exceptionally* difficult (by the way, this should also answer @FourthWorld's question about why scripting languages tend not to have general multi-threading - its mainly because most scripting languages are still derived from their original implementation because writing them is incredibly difficult in the first place, and most original implementations of most scripting languages were done without regard for threading!).
The second is that there is no point in adding features to LiveCode (especially ones which come with a huge engineering cost) unless they can benefit *most* users of LiveCode. How many of you actually want to have to deal with all the intricacies of multi-threading, with its locks, semaphores, dead-locks and all that stuff? Surely it is better we choose very high-level and appropriate abstractions which are easy to use, work flawlessly and allow you to do 99% of what you could do in a lower-level language without the huge amount of technical baggage?
I'm pretty sure the combination of non-blocking 'I/O', non-recursive wait, and restricted worker tasks would give LiveCode an arsenal of multi-threading-related capabilities that would put it on a par with any other language-du-jour.
LiveCode's language development and evolution might be slow - however, its important to remember that the language itself has now been around in some form for 31 years... Which is longer than 6 of the languages in the top 8 of TIOBE, the only ones which have been around for longer are C and C++ - and C++ only beat us by 2 years (although given C++ via Cfront was absolutely atrocious - I think we can probably say our language has been for longer than usable C++!). It has stood the test of time, and needs to continue to do so.