The Delphi Geek
random ramblings on Delphi, programming, Delphi programming, and all the rest
Tuesday, January 31, 2012
OmniThreadLibrary Documentation–an Outline
Saturday, January 28, 2012
A Sign of Maturity
No IDE is mature until it has a TSmiley component.
--Anonymous
This week I got a sudden urge to write TSmiley component for Smart Mobile Studio IDE. After all, what is a development environment without a smiley?
My TSmiley is not an enterprise-y solution like latest Nick’s revisit of the old theme ;), oh no, it is a lean and mean component without any special bells and whistles. You can select the smiley’s emotion and it will change the look. And that’s it.
I thought that a story about TSmiley for Smart would be instructive for you, dear reader, as this is almost the simplest component one can write. Read on to see how writing a component for Smart is very similar to writing a component for Delphi and how it is also utterly different.
GpDelphiUnits update
Friday, January 20, 2012
Handling Touch Events
I mainly started playing with the Smart Mobile Studio because I wanted to write some stuff for my iPad. OK, there’s a small issue of possibly producing client applications for my job and maybe for some freeware/shareware stuff I’m thinking about, but this is not on the horizon yet. Therefore, iPad. (And I don’t have iPhone and I don’t care about writing stuff for my wife’s Android, so – iPad.) And writing for iPad means supporting touch gestures.
[Yes, I know I could use Objective-C but – bleuch, really? – and I could use FireMonkey but I don’t have a Mac and don’t want to buy one just for playing around and I can’t make Platform Assistant run in a Hackintosh, Therefore, Smart.]
Touch is natively supported in Smart. Gestures are not (but that may change before the release). What’s the difference, you ask? Touch subsystem will give you information about separate fingers like – finger has touched – another finger has touched – first finger was moved – both fingers were moved – while gesture subsystem will give you a simple – zoom gesture in progress. But hey, let’s start with touch. Lots and lots of stuff can be written with just the information about the fingers touching the screen.
Tuesday, January 17, 2012
Improved Painting
When I wrote about my first Smart Mobile Studio program I mentioned that it failed on iPad (and would probably fail on iPhone too but I couldn’t test that) because the Paint code took too long and the iOS simply aborted it. As far as I know there are two ways to fix this in JavaScript – you can either move the calculation to a background thread using a Web worker mechanism or split the Paint into multiple parts where each part only calculates and paints small part of the screen and then returns control to the browser. For the time being I went with the latter solution but that will not prevent me from testing the Web worker approach at some time.
OmniThreadLibrary in Practice [2a]–Backround Worker and List Partitioning
Today I’m revisiting example from November 2011. This time I’ll solve it using the new Parallel.BackgroundWorker abstraction.
Part of the Zarko’s requirements (see the original post for full text) was a cancellation support.
At any time the "master" thread could be signaled to terminate (from the app's main thread) all child threads (and itself).
When I was originally implementing this using the Parallel.Pipeline abstraction I had to put some work into the cancellation support. The main reason for this was inappropriate abstraction – Parallel.Pipeline is designed around the data flow processing and supports only a basic cancellation of the “stop everything” type. To be fair, that would comply with the Zarko’s requirements, but I wanted nicer solution where you can stop processing and then continue with a new work item without rebuilding the background thread mechanism. [Pipeline solution inherently supports cancellation but you cannot recover from it – to continue processing one would have to destroy the pipeline and build a new one.]
Tuesday, January 10, 2012
Background Worker
When I wrote OmniThreadLibrary in Practice [2]–Background Worker and List Partitioning in November, I noticed that OmniThreadLibrary needed another high-level abstraction, a background worker. I published some ideas on how the background worker interface could look. Those ideas were later developed in a full-fledged high-level solution.
Background worker is designed around the concept of a work unit. You create a worker, which spawns one or more background threads, and then schedule work units to it. When they are processed, background worker notifies you so you can process the result. Work items are queued so you can schedule many work items at once and background thread will then process them one by one. [Actually, Parallel.Pipeline is used as a base for the implementation.]
Handling Mouse Events in Smart Mobile Studio
After I finished my very first Smart program, I wanted to enhance it with some interactivity. I wanted the user to be able to navigate through the Mandelbrot set by using mouse and touch. For now, I have only implemented the mouse part, touch events will be handled later (soon, I hope).
I wanted to achieve few different ways of navigation:
- Click & drag with the left mouse button shows a rectangle on the screen. When the mouse button is released, program zooms in to display the selected rectangle.
- Double-clicking zooms in around the point of click.
- Right-clicking zooms out around the center of the image.
- Right-click & drag shows a line on the screen. When the mouse button is released, program moves the current view (point of first click is moved to the point of release).
- If a drag operation is in progress, user can click and release the other mouse button (left if right-drag is in progress, right if left-drag is in progress) to cancel the drag operation.
You can see the navigation in action in this (very low quality, sorry) YouTube video.
Saturday, January 07, 2012
My First Smart Program
Last week I wrote about my first impressions about the OP4JS/Smart Mobile Studio project. This week I’ll show you my first program.
Wednesday, January 04, 2012
First Steps with Smart Mobile Studio
“JavaScript is Assembly Language for the Web”
[original author unknown]
I learned about that idea from the omnipresent Hanselmann and I fully agree with it. JavaScript has its good moments, but they are completely outweighed by the total mess and confusion that is the JavaScript language and by some awful decisions made by the original designer.
If you don’t believe me, try answering the following question. “What does JavaScript expression ++[[]][+[]]+[+[]] evaluate to?” I’m not kidding you – this mix of plus signs and square brackets is a legit JavaScript expression and its result is ‘10’. [For proof, see Stackoverflow question Can you explain why ++[[]][+[]]+[+[]] = 10.]
As you may have guessed, I don’t like programming in JavaScript. I can read it on a good day but I never managed to write more than few lines of JavaScript code. On the other hand, I would like to write a browser application from time to time, as that would allow me to run such an app on different platforms (and by that I mean a PC, Mac, iOS, and Android).
When I learned about the OP4JS project, which promised a cross-compiler from Delphi-like language to a JavaScript and an integrated development editor, I was almost ecstatic with joy. Truly, such a tool would be a great addition to my toolset – if the authors managed to pull it through. It looked like a tough project for just two people. But … as the Lennart (one of the authors) likes to say – one good Delphi developer is worth hundred mouse-pushers (or something to that effect). They struggled and they succeeded. Just before the end of 2011, select few people received the alpha version of the IDE so that we could play with it over the holiday season.
I’ve got the permission from the authors to write about it so in the next weeks you can expect posts that will follow my road to Delphi-generated HTML+JavaScript applications.
Friday, December 30, 2011
OmniThreadLibrary 3.0
As promised, I’m releasing OmniThreadLibrary with 64-bit support today!
Get it now: ZIP, SVN, UML diagrams (provided by Rich Shealer).
If you’ll be using it in production, wait until Tuesday as I won’t be fixing any bugs over the weekend and on the Monday there is a public holiday here in Slovenia.
Wednesday, December 28, 2011
OmniThreadLibrary 3.0 beta
OmniThreadLibrary 3.0 beta is available for download. Please test and report any problems.
Version 3.0 will be officially released on Friday.
How to Find a Missing _Release
For quite some time, thread pool in OmniThreadLibrary had a weird problem – if you scheduled more than 80 tasks in one go, FastMM would report memory leaks when application was terminated. It bothered me, of course, but I could never find the real reason behind the problem. And so I left the code “as is” and said to myself that nobody would encounter it in practice, anyway.
And then Ĺ˝arko came and wrote about me on his blog :( In case you are living in a dark cave and didn’t hear of him – Ĺ˝arko runs immensely popular Delphi site at About.com. His testing (and most of all his highly reproducible test case) gave me a new energy to pursue the problem.
The reason for the memory leak was a reference count leak in TOmniInterfaceDictionary, which is now fixed in the SVN. I also found some very tricky race conditions in TOmniTask.Execute and TOmniTask.Terminate and a cause for weird "A call to an OS function failed" error in DispatchEvent. All in all, I had two very productive bug-hunting nights. But that’s not why I started writing this article. I wanted to tell you a debugging story titled “How to find a missing Release.”
Wednesday, December 21, 2011
… 62, 63, 64!
It is my pleasure to announce the availability of OmniThreadLibrary 3.0 beta. The main focus of this release is on the 64-bit support. Every part of OmniThreadLibrary is now compatible with the Windows 64-bit platform!
The current status of the code is “It works on my machine”. That is not pretty encouraging and I would really like to see some external testing. If you are using OTL, please get the fresh copy from the SVN and check if your applications are still working. 64-bit bugs are not a big problem right now – they will be squashed before any 64-bit OTL code goes into production – but I’d really like not to break existing code. Thanks!
Tuesday, December 20, 2011
… 54, 55, 56 …
Thread pool is working, other tests are passing nicely and it looks like you’ll be able to get your hands on the alpha version tomorrow.
Monday, December 19, 2011
… 47, 48, 49 …
Second milestone reached – dynamic lock-free queue works in 64 bits as does blocking collection. The latter is basis for most high-level threading abstractions in the OmniThreadLibrary so this is quite an important milestone.
Thread pool was not tested yet so the code is still in “look but don’t touch state”.
Sunday, December 18, 2011
… 39, 40, 41 …
First milestone reached!
“Bounded” containers (fixed-size stack and queue) are now working fine both in 32- and 64- bits!
This is quite an important step because those containers are used to transfer data between OTL controllers and threads (i.e. they are used inside the Comm mechanism). They also contained quite some assembly code.
Great thanks to GJ who did all hard work to make x64 OTL possible!
Friday, December 16, 2011
32, 33, 34 …
Initial work has been committed on the x64 development branch: http://omnithreadlibrary.googlecode.com/svn/branches/x64
Current status is “Look but don’t use”. Many parts are still broken.
Thursday, December 15, 2011
Creating an Object from an Unconstrained Generic Class
As you know if you follow my blog, OmniThreadLibrary now offers a simple way to do optimistic and pessimistic atomic initialization which works for interfaces, objects and (in the case of the pessimistic initialization), anything else. [In case you missed those articles - I also discussed a comparison of both methods and wrote a short post about the third approach to initialization.]
A typical usage of both types of initialization would be:
var sl: TStringList; ol: Locked<TObjectList>; Atomic<TStringList>.Initialize(sl, function: TStringList begin Result := TStringList.Create; end); ol.Initialize( function: TObjectList begin Result := TObjectList.Create; end);
As you can see, this is pretty long-winded. If you are initializing an interface, then you’ll usually have written a factory method already and the code would be much simpler (example below this paragraph) but in the case of objects this is not very typical.
Atomic<IGpIntegerList>.Initialize(list, TGpIntegerList.CreateInterface);
So I thought – both Atomic and Locked already know what entity type they wrap around so calling a constructor from inside Initialize would be trivial, eh? I could then write a simplified version
Atomic<TStringList>.Initialize(sl); ol.Initialize;
and use the longer version only when needed, for example to initialize interfaces or to call a non-default object constructor. What could possibly go wrong?
Sunday, December 04, 2011
Busy-Wait Initialization
The algorithm itself is very simple:
class function BusyWait<T>.Initialize(var storage: T; factory: TFactory): T; begin if storage = nil then begin if InterlockedCompareExchangePointer( PPointer(@storage)^, PPointer(@factory)^, nil) = nil then storage := factory() end; while PPointer(@storage)^ = PPointer(@factory)^ do Sleep(0); end;[This is not exactly the algorithm GJ proposed but my modified version, changed to work in a generic class.]
Friday, December 02, 2011
On Optimistic and Pessimistic Initialization
When you want to initialize a shared resource in a multithreaded application, you have two possibilities to choose from – optimistic and pessimistic. The difference between them is visible from the pseudocode.
var
Shared: T;
procedure OptimisticInitializer;
var
temp: T;
begin
if not assigned(Shared) then begin
temp := T.Create;
if not AtomicallyTestAndStore(Shared, nil, temp) then
temp.Free;
end;
end;
procedure PessimisticInitializer;
begin
if not assigned(Shared) then begin
Lock;
try
if not assigned(Shared) then
Shared := T.Create;
finally Unlock; end;
end;
end;
Thursday, December 01, 2011
Fibonacci Numbers the Weird Way
Generating Fibonacci numbers with an enumerator
for i in Fibonacci(10) do Writeln(i);Of course you need a Fibonacci-implementing enumerator. I wrote one on 2007 and it uses the iterative approach. Read more in my old article Fun with enumerators, part 6 – generators.
Generating Fibonacci numbers with anonymous methods
This one was prepared for ITDevCon 2011 as an example of tricky (but pretty much useless) example of what can be done using anonymous methods.
Tuesday, November 29, 2011
Per-object locking
I was always holding the opinion that locks should be as granular as possible. Putting many small locks around many unrelated pieces of code is better then using one giant lock for everything.
To make this simpler, OmniThreadLibrary includes a very useful record called TOmniCS which allows you to do locking without doing any upfront initialization. Just declare it and you’re ready to go. [You can read more about it in my previous blog post.]
Monday, November 28, 2011
Atomic interface initialization
type TOmniCS = record strict private ocsSync: IOmniCriticalSection; function GetSyncObj: TSynchroObject; public procedure Initialize; procedure Acquire; inline; procedure Release; inline; property SyncObj: TSynchroObject read GetSyncObj; end;As records don’t provide automatic initialization via parameterless constructor, the code is slightly tricky. The record contains a field (ocsSync) that contains the interface reference used to do real work. This interface is initialized in the Initialize method, which is in turn called from the Acquire and Release.
procedure TOmniCS.Acquire; begin Initialize; ocsSync.Acquire; end;
Tuesday, November 15, 2011
OmniThreadLibrary needs more unit tests
Eh. How true. :( Care to step in?
It’s really simple. Take a sample application (for example 37_ParallelJoin), check what it’s doing and convert it into a unit test. [In this example, first button should cause a wait of about 3 sec and second button should cause a wait of about 5 sec. That’s all.] If the application you have chosen seems too complicated to be converted to a unit test, just ignore it and select another.
Why? Because I’ll be converting OmniThreadLibrary to support 64-bit and FireMonkey in the next week and I really could use a safety net which would ensure at least that I don’t break everything at once.
Why you? Because I’ll be converting OmniThreadLibrary to … but I already said that. If you can spend some time on that, then I don’t have to and everything will be finished quicker.
For really curious people – why 37_ParallelJoin? Because it is broken in the current SVN version. Parallel.Join.NumProc is not working correctly and I only noticed it by chance. [Fixing the bug right now …]
If you like OmniThreadLibrary but don’t feel competent enough to help developing it, this is your chance to step in and help the development effort!
Wednesday, November 09, 2011
TOmniValue handles arrays, hashes and records
Arrays
For quite some time, TOmniValue record has the ability to store arrays. You would useTOmniValue.Create([1, 2, ’OTL’, TButton.Create(nil)])and some magic would store this array inside TOmniValue.
The problem, though, was that this magic was quite lame. The array was converted to a ‘variant array’ and you could only access its elements as Variant type. This, besides other things, meant that it was not simple to store pointers, interfaces and objects in TOmniValue array. Or, better said, it was simple to store them but not simple to retrieve them. You needed some ugly casting like
o := TButton(NativeUInt(ov[1]));Since today, TOmniValue supports native arrays, that is, each item in the array is again of the TOmniValue type.
Thursday, November 03, 2011
OmniThreadLibrary in Practice [2]–Background Worker and List Partitioning
Here's my (simplified) task I would like to solve using OTL (Delphi XE) - my real-world task is somehow more complicated but can be described as:
input: a string. output: a TStringList containing characters (one per entry) of the input string.
Example: input: "delphi"
A background thread ("master") grabs the input string and splits it into several pieces (let's say 2): "del" and "phi". For each of the split strings a new thread ("child") is created that fills in the TStringList (output) with characters from the section of the string it receives.
At any time the "master" thread could be signaled to terminate (from the app's main thread) all child threads (and itself).
When everything is done the app's main thread processes the string list.
Preferably, the order of the characters should (when all ends) be 'd', 'e', 'l', 'p', 'h', 'i' (note that characters are actually items in the resulting string list).
Saturday, October 29, 2011
ITDevCon 2011–recap
ITDevCon 2011 has closed its doors and I’m back at home, completely washed out. It was tiresome but it was also fun!
All the sessions I’ve visited were interesting and I always managed to learn something new. If I would have to expose three most important products I didn’t knew before, I would mention (in the order I learned about them) CopyCat, a great database replication engine which you can compile into your application; Delphi Relax, an extension to Delphi’s WebBroker and DataSnap REST architecture; and DORM, a new ORM for Delphi.
Thursday, October 27, 2011
ITDevCon 2011
Just few photos from the opening session …
Wednesday, October 26, 2011
Nasty COM regression in XE2
David Heffernan found a nasty RTL bug in XE2 COM implementation.
Is COM broken in XE2, and how might I work around it?
I’ve found a workaround (see the link above), but it is ugly and this should really be fixed in the next XE2 update so please – vote on the QC #100414!
Update: XE2 Update 2 fixes the bug described above. Great response time from Embarcadero!
Saturday, October 22, 2011
Multithreading Made Simple–additional material
Thank you for listening to my CodeRage 6 presentation! I’m very sorry that there were some issues with the sound that were caused by network problems :( If you want to look at the presentation again (or for the first time), please go to the Embarcadero CodeCentral or download the presentation from my Dropbox.
To help you understanding the complicated world of multithreading I’ve repacked the complete presentation in a longish PDF with slides and a transcript of my talk. (Actually, it was done vice versa – first I wrote that script and only then I prepared the presentation based on the script.) You can also download the code that was used for the presentation.
If you have any questions or if you asked me something after the presentation and I didn’t understand your question and answered something completely unrelated or even if my answer was too short and you want to learn more - feel free to leave a comment here or open a new topic in the forum.
Friday, October 21, 2011
Multithreading Made Simple
Keep in mind – my session on high-level OmniThreadLibrary stuff goes on air at 06:00 AM PDT / 15:00 CET.
Thursday, October 20, 2011
OmniThreadLibrary in Practice [1]–Web Download and Database Storage
From time to time I get a question on the OmniThreadLibrary forum that could be of interest to other OmniThreadLibrary users. As I believe that many of you don’t follow that forum I have decided to repost such questions on the blog (and provide answers, of course).
The first question in this series was asked by GoustiFruit:
I need to download a list of web pages, extract data on them and then store these data in a SQLite database. The downloading/extracting part will happen in multiple threads (I'm using Synapse), but querying the database needs to be done asynchronously as I can only have one concurrent access to it.
So I'd like to know how (conceptually) I could implement that ? My first idea is to run one single thread for querying the DB, run several threads for each Url to download/analyse and then exchange messages between these threads and the querying thread, with the extracted data as a parameter: does it make sense or am I totally wrong? I also read things about the connection pool concept but I'm not sure if it applies when only one connection is allowed at one time?
Sunday, October 16, 2011
CodeRage 6 is Starting!
Tomorrow starts the CodeRage week!
My presentation is scheduled for Friday, 21st, at 06:00 PDT / 15:00 CET, which is early for the West coast folks but great for East cost and us Europeans. See you there!
Tuesday, October 11, 2011
OmniThreadLibrary 2.2
Only three months since 2.1 and a new release is already here? What’s going on?
I had to change some things to make OTL work in XE2 and although I could simply release new files as a patch I noticed that I’ve also done quite some work on exception handling and that I could equally well wrap everything in a new release.
Here it is: ZIP, SVN, UML diagrams (provided by Rich Shealer; Rich, thanks!).
