Sunday, July 12, 2015

OmniThreadLibrary Book Update

After a (much too) long time, I have (finally) found some time to work on my book “Parallel Programming with OmniThreadLibrary”. For starters, I have updated existing content so that the current version (3.04) is properly documented. The following topics were added/updated:

  • Documented Parallel.For.
  • Documented Parallel.Map.
  • Documented TOmniBlockCollection.ToArray<T>.
  • Added longer example for Parallel.For.
  • Documented IOmniTaskConfig.SetPriority and .ThreadPool.
  • Documented Parallel.Pipeline.PipelineStage[] property.
  • Documented new demos.
  • Documented other changes and additions.
  • Updated hyperlinks.

Update is free (as it always was and as it will always be) for all owners of the book. You probably already received an email with details. If not, you should just go to LeanPub and download the new version.

You can buy the book (and with that support the OmniThreadLibrary development) here.

GpSQLBuilder Improvements

Thanks to [leledumbo], GpSQLBuilder now works with the FPC pascal and supports the INSERT statement.

You can now write statements such as:

  query := CreateGpSQLBuilder
.&Set(COL_1, [42])
.&Set(COL_2, 'abc')

Which will give you:

INSERT INTO Test (Column1, Column2) VALUES (42, 'abc')

Saturday, July 04, 2015

Using OmniThreadLibrary’s Message Queue with a TThread Worker

A reader recently asked about using OmniThreadLibrary’s communication channels with a TThread-based worker thread so I prepared a simple example, now part of the OTL repository (stored in the folder examples\TThread communication).

Two separate topics are covered in this example:

  • Sending data from any thread (main or background) to a TThread-based worker.
  • Sending data from a TThread-based worker to a form.

Friday, May 15, 2015

OmniThreadLibrary – GetIt!

OmniThreadLibrary is now available on GetIt so it can be installed in XE8 with a single click!

Go, Embarcadero! That’s really great!

Thursday, May 14, 2015

XE8 links

In case you’d like to know more about the RAD Studio/Delphi/C++ Builder XE8, following links will give you a good starting point.

Thursday, May 07, 2015

Presenting XE8 in Slovenia

Next Thursday (14th) I’ll be presenting XE8 in Ljubljana. We’ll be doing the standard “launch” combo – official (English) slides and demos + Slovenian presentation.

Register here!

Thursday, April 30, 2015

Runtime SQL Query Builder v3

There’s a whole new SQL Query Builder available on GitHub. I have basically rebuilt it from scratch as the previous “architecture” (it does not actually deserve to be called that) was just slapping strings together and that approach had reached its limits.

Query builder is now implemented as three units – GpSQLBuilder.AST implements an abstract syntax tree for SQL queries, GpSQLBuilder.Serialize knows how to serialize this tree to a string and GpSQLBuilder creates the tree and calls the serializer when necessary. Now it will be much simpler to a) add support for new SQL keywords and b) create different serializers, for example a ‘pretty print’ version. (If anybody wants to tackle this last task, please go ahead – I’ll be happy to merge a pretty print serializer into the master branch.)

In addition to that I have added support for different Joins: .InnerJoin, .RightJoin, and .FullJoin are now supported in addition to .LeftJoin.

A .&Case method was redesigned a bit. It now returns an interface which can be sent as a parameter to a .Select, .Column, and .OrderBy methods. You can use it like this:

  query := CreateGpSQLBuilder
.When([COL_2, '< 0']).&Then('0')
.When([COL_2, '> 100']).&Then('2')


  query := CreateGpSQLBuilder;
.When([COL_2, '< 0']).&Then(COL_3)

New version also supports the .Distinct select flag.

I’ve created a unit test suite (actually I did that before the redesign so that I could refactor my code in piece) which now includes 51 tests, all passing.

Wednesday, April 29, 2015

Portable OmniThreadLibrary

If you care about running OmniThreadLibrary on mobile devices and on OS X, please join the OmniThreadLibrary-For-Mobile-DevelopmentProject page on Google+ where Sean has started to document his progress on doing exactly that – breaking the chains of Windows and bringing OmniThreadLibrary to all supported platforms!

Go, Sean!

Saturday, April 25, 2015

Value Never Used – Or Is It?

Sometimes, dcc32 is just plain stupid …

I have this code in the OmniThreadLibrary:

function TOmniThreadPool.Cancel(taskID: int64): boolean;
res: TOmniWaitableValue;
{$IF CompilerVersion >= 22}
Result := false; // not really used
res := TOmniWaitableValue.Create;
otpWorkerTask.Invoke(@TOTPWorker.Cancel, [taskID, res]);
Result := res.Value;
finally FreeAndNil(res); end;

The IFDEF part is there because otherwise compiler complains about result being potentially undefined.

[DCC Warning] OtlThreadPool.pas(1315): W1035 Return value of function 'TOmniThreadPool.Cancel' might be undefined

I’ve first observed this with the XE and it was fixed after the XE2 (can’t repeat this with XE8, but I didn’t check every compiler inbetween.)

Friday, April 17, 2015

New Home for OmniThreadLibrary

OmniThreadLibrary has been moved from Google Code to GitHub.

I still have to move existing issues as they were not moved automatically.

Thursday, April 16, 2015

New Home for My Units

My collection of open-sourced units has been moved from Google Code to GitHub.

Wednesday, April 08, 2015

XE8 is out …

… and OmniThreadLibrary works fine with it. (That’s it. Just wanted to let you know.)

Friday, April 03, 2015

Runtime SQL Query Builder

I don’t want to use long SQL strings in the code.


Firstly, it is a pain to write long multiline strings in Object Pascal. (Embarcadero, are you listening? Can we please get multiline strings in Delphi? Please?)

Secondly, I’m very OCD when it comes to compiler watching my every step. I absolutely hate runtime errors and I want every problem to be detected during the compilation. That includes typos in database field names and changes attributed to the entropy (i.e. changes in the database structure).

On a tangent, that’s why we are creating and managing tables and databases in the code. We have all fields defined as constants, all SQL statements created in runtime and everything stored under version control.Upgrading a database to a version required by the program is therefore a very simple operation. (Downgrading is still a problem. Downgrading is hard.)

Thirdly, concatenating query strings together when you are dynamically building a query string based on the conditions in the program is a mess.

That’s why long years ago I created a simple runtime query builder. It was dormant (in the “good enough for me” state) for a long time but recently I required more functionality from it and I extended it further. It is now in a state which may be useful for somebody else but me so I’m releasing it as an open source under a BSD license.

For impatient: Get GpSQLBuilder on GitHub.

Thursday, March 19, 2015

Unit Testing Recap & Downloads

The Unit Testing workshop was pretty much full.

2015-03-19 11.06.12

It was good to see that many interested Delphi programmers in one room. Thanks for coming, everybody!

The downloads for the workshop are now online.

Thursday, March 12, 2015

What’s New in Delphi XXXX

A great list of “What’s new” for Delphis from 3 to XE7 can be found on StackOverflow.

(just noticed and thought I’d better pass this on)

Wednesday, March 11, 2015

Unit Testing, Mocking, Inversion of Control

On March 19th (that’s next Thursday), I’ll be leading a workshop dedicated to unit testing Delphi programs. We’ll start with basics and and cover different tools (DUnit, DUnit2, DUnitX, TestInsight) and different programming methodologies.

Register here.

Sunday, March 01, 2015

OmniThreadLibrary 3.04

OmniThreadLibrary 3.04 is now released. Get it here or check out the release-3.04 tag (or just follow the trunk, which is the best way to experience the OmniThreadLibrary).

Some other links you may need:

Home page:
Google+ community:
Issue tracker:
SVN checkout instructions:
Author's blog:
Author's home page:
Documentation wiki:
Documentation book:


New features

  • Implemented simple and fast Parallel.&For which supports only integer ranges.
  • Implemented Parallel.Map.
  • Added overloaded Execute methods to IOmniParallelInitializedLoop and IOmniParallelInitializedLoop<T> so that IOmniTask parameter can be passed to the executor.
  • Implemented Run overloads that internally call Invoke to start thread worker.
  • Implemented TOmniValue.HasArrayItem.
  • Implemented TWaitFor which supports waiting any/all and is not limited to 63 objects.
  • IOmniTaskControl can wait on any number of comm handles and wait objects. That enables support for >60 tasks in the OtlThreadPool.
  • Implemented TOmniBlockingCollection.ToArray<T>.
  • NumTasks parameter (OtlParallel) can be negative. In that case, specified number of cores will be reserved for other purposes and all other will be used for processing.
  • Example: If NumTasks(-2) is used when process has access to 8 cores, 6 of them (8 - 2) will be used to run the task. 
  • Removed project groups.
  • Tested with 2007-XE7.

Bug fixes

  • Fixed race condition in IOmniPipeline termination code [tnx to Dean Hill].
  • Creating parameters with the array overload (IOmniTaskControl.SetParameters(['From', 0, 'To', 99])) was not working.
  • Fixed problems in demos 33_BlockingCollection and 47_TaskConfig.

New demos

  • 55_ForEachProgress: Demonstrates progress bar updating from a ForEach loop.
  • 56_RunInvoke: Simplified 'run & invoke' low-level API.
  • 57_For: Simple and fast parallel for.
  • 58_ForVsForEach: Speed comparison between Parallel.ForEach, Parallel.For, and TParallel.For (XE7+).
  • 59_TWaitFor: Demo for the new TWaitFor class.
  • 60_Map: Demonstrates the new Parallel.Map abstraction.
  • 61_CollectionToArray: Demonstrates the new TOmniBlockingCollection.ToArray<T> method

Wednesday, February 18, 2015

OmniThreadLibrary 3.04 Release Candidate

RC for the new OmniThreadLibrary release is available here.

This version should work with Delphis from 2007 to XE7. Win32 and Win64 are supported for Console and VCL applications.

Tuesday, February 03, 2015

Converting Collection to an Array

Blocking collections (IOmniBlockingCollection) are basic elements for data storage and transfer in many high-level OmniThreadLibrary abstractions. They can, however, be somewhat clumsy when you want to read data from them, as there is no indexed access, just the basic “give me next element” enumeration.

To help a bit, SVN now includes three new class functions in the TOmniBlockingCollection class – ToArray<T>, ToArrayIntf<T>, and ToArrayRec<T>.

class function ToArray<T>(coll: IOmniBlockingCollection):
class function ToArrayIntf<T: IInterface>(
IOmniBlockingCollection): TArray<T>;

class function ToArrayRec<T: record>(
IOmniBlockingCollection): TArray<T>;

Friday, January 30, 2015

Parallel Map

At my latest parallel programming presentation a participant suggested that I should extend the OmniThreadLibrary with a parallel mapping abstraction. Dear sir, here is a gift for you.

numbers: TArray<integer>;
odds : TArray<string>;
//initialize the `numbers` array (not shown)
odds := Parallel.Map<integer,string>(numbers,
function (const source: integer; var dest: string): boolean
Result := Odd(source);
if Result then
dest := IntTostr(source);
//do something with the `odds` array (not shown)

Saturday, January 10, 2015

Implementing Record Assignment Operator [2]

Yesterday I hinted at having a working (and easy to use) solution which allows you to detect a record assignment (or copying, if you want) and to access both records (left and right part of the assignment operation). You can also modify record data when an assignment is detected. I also mentioned that my approach is very ugly, unstable, likely to cause problems in future Delphis and so on. You should read this article for the technical details, not to really use my code in an application. You have been warned!

Before I jump to hardcode Delphi stuff, I’d like to mention few different approaches that various smart people have already implemented. Most of them slipped below my radar in the past – and I’m guessing this may be the case for you too – so I’m listing them here in case you want to do more research on the topic.

Friday, January 09, 2015

Implementing Record Assignment Operator [1]

Following the yesterday’s hunch, I did some research and I came up with a way to detect when a record is copied (simple, supported, working everywhere) and even to access both records (source and target) during that operation (unsafe, unsupported and currently working only for Win32).

Now I can write such code:

Thursday, January 08, 2015

Implementing Destructor for a Record

Smart records in Object Pascal are very nice, but they have a stupid limitation – you cannot implement a destructor for a record.


A solution for that is quite simple and can be found all over the internet – add an interface to this record and implement the cleanup in this interface. To make it even simpler, you can use the IGpAutoExecute interface from the completely free GpStuff unit.

Thursday, December 25, 2014

Blast from the past: Turbo Pascal raytracer

Paweł’s recent post reminded me of a veeeeeery old raytracer I wrote in years 1985/89. (Yes, young ones, we had computers then!)

Header states:

  Computer: VAX-11/750
  Language: Pascal V2
  Graphics: VT100

  Computer: IBM-PC
  Language: Turbo Pascal 4.0
  Graphics: EGA 640 x 350 x 16

  Computer: IBM-PC/AT
  Language: Turbo Pascal 5.0
  Graphics: VGA 800 x 600 x 256

Quite a blast from the past – the 800 x 600 in 256 colors (out of a great palette of 262144 colors!) was more or less the greatest graphic card which you could get for PC at that time. And the first version was running on a VT100 terminal with an additional graphics board. Sadly, I don’t have that code anymore :(.

Saturday, December 13, 2014

Attribute-based Command Line Parsing

Oh, command line parsing, the old enemy of mine!

imageIn ye olden days, when I was learning Pascal, I did some programming on VAX/VMS systems, where you could (and should) leave the job of command line parsing to the DCL – the command line interpreter (something like CMD.EXE on Windows). You just wrote a definition file (see example on the right, found on the web) and DCL did the rest.

Since those days I hated that I have to parse command line programmatically. Sure, there were parsing libraries – and I wrote few of them myself – but I was never happy with them. There was always too much code to write.

Then I was looking for good examples on using attributes in Delphi and suddenly it occurred to me that I could use them for command line parsing, too! And that’s how GpCommandLineParser was born.

Before continuing, I should mention that I have based it (concept-wise, implementation is all my own) on the CommandParser unit, which comes with Delphi and can be found in Samples\Object Pascal\Database\dbExpress\Utils. This is a very nice but mostly unknown command line parser which I can definitely recommend.

Thursday, November 27, 2014

OmniThreadLibrary 3.04 beta 1 – testers needed

I have (finally!) implemented support for more than 60 simultaneous tasks in the OTL thread pool and for more than 60 waitable events in the IOmniTaskControl. This also enables support for massively parallel execution in OtlParallel abstractions. IOW, Parallel.ForEach will run correctly on machines with 64 and more cores without needing to call NumTasks(60).

I’ve been testing this change and I think that it’s working correctly, but it is a big (and potentially dangerous) modification and so I’d like to see additional testers trying the new version in real programs before I submit it to the SVN.

So – if you like to live on the edge, if you’d like to help improve OTL and especially (but not required!) if you can test the code on a machine with 64 or more cores, please download the 3.04b1 from Dropbox and try it out. You can post reports here or send them to my email (my address is in the header of every OmniThreadLibrary file). In case of a problem, a short, repeatable, self-contained example will be of an immense help.


Wednesday, November 26, 2014

Parallel programming with XE7–reminder

A note for Slovenian readers.

Ne pozabite – jutri bom predstavil novo knjižnico System.Threading, ki olajša razvoj hitrih in odzivnih programov za vse platforme, ki jih podpira RAD Studio – Windows, OS X, iOS, Android – ter v obeh programskih jezikih – Delphi in C++. Ogledali si bomo tudi novosti v knjižnici OmniThreadLibrary.

Za več podatkov in prijavo kliknite tu!

Wednesday, November 12, 2014

Pohitrite programe z RAD Studiom XE7

This is an invitation for the XE7 workshop in Slovenia which is targeted at Slovenian programmers.

RAD Studio XE7 prinaša nov način paralelizacije programov. S kodo, zbrano v enoti System.Threading lahko na enostaven način pohitrite nekatere funkcije v programih, tako da se izvajajo sočasno z drugo kodo. Še lepše - System.Threading deluje na vseh podprtih platformah, torej poleg Windows tudi na OS X, iOS in Androidu. Na delavnici si bomo podrobno ogledali nove načine paralelizacije in pregledali druge knjižnice, ki podpirajo hkratno (paralelno) izvajanje v okolju Windows.

Predavanje bo v četrtek, 27. novembra, 2014.

Kliknite za prijavo

Wednesday, October 29, 2014

DAPUG 2014 Workshop

Presentations and code samples from DAPUG 2014 workshop are now available online.

Big thanks to organizers (and especially Jens) – we had great time in Denmark! Hope to see you again some time!

Tuesday, October 21, 2014

DAPUG workshop

Hesselet hotel is very nice and workshop is proceeding smoothly.


Just saying :)

Monday, September 29, 2014

Fixing XE7 + Android SDK 23 ZipAlign Problem

If you install RAD Studio XE7 and then upgrade Android SDK to version 23, you won’t be able to deploy applications to Android devices anymore.


The reason for that is that ZipAlign.exe was moved out of sdk\tools folder in SDK 23 and XE7’s deployment process cannot find it anymore. Now it is located in sdk\build-tools\20.0.0, but only is Android SDK Build-tools rev. 20 are installed, which doesn’t happen automatically.


To fix my Delphi I first had to install Build tools rev. 20. Then I copied sdk\build-tools\20.0.0\zipalign.exe to sdk\tools\zipalign.exe. That fixed the deployment problem.

I’m hoping Embarcadero will fix this in the next update, but for now you can use this workaround.

[Android sdk folder can be found in c:\Users\Public\Documents\Embarcadero\Studio\15.0\PlatformSDKs\adt-bundle-windows-x86-20131030\sdk]

Tuesday, September 23, 2014

Delphi programmer wanted

This is a job offer for a full time programming job in Ljubljana.

Iščemo Delphi programerja za dolgotrajno razmerje; človeka, ki se ne ustraši stare kode in z veseljem programira s sodobnimi orodji. [XE2, prehod na sodobno različico je že v teku in ga bo pomagal zaključiti prav programer ali programerka, ki ga iščemo.] Delo se opravlja v pisarni v Ljubljani.

Več o podjetju: Kontakt: primoz (pri)