Wednesday, September 28, 2011

NeverSleepOnThreadContention–NOT!

FastMM is a wonderful memory manager, but it can slow down quite a lot when used in multithreading environment. While Pierre has implemented some conditional defines that could help the multithreaded code, namely NeverSleepOnThreadContention and SwitchToThread, I’m now making a point that you shouldn’t ever use them! Just see for yourself.

Friday, September 16, 2011

Meet Me in Verona

SpeakerButtonI know that XE2 on Win64, OS/X and iOS is all the rage but some of us (or is it most of us?) still have to make living in the Win32 world. That’s why my ITDevCon 2011 talks are not focused into specific technologies but into techniques and tools that will make your life easier. (At least your life as a programmer, that is.)

If you have time and you live close enough, come to Verona at the end of October and meet many interesting people. Lots of speakers, three separate tracks, free lunch and wifi – what do you want more? David I is rumored to be there, Marco Cantù will lead sessions all the time and you’ll have a chance to talk to me. I’ll be giving four sessions, some targeted at beginners, some at experienced programmers. (All between those extremes are also invited, of course.)

Monday, September 12, 2011

Life after 2.1: Parallel data production [Introducing Parallel.Task]

An interesting problem appeared on StackOverflow shortly ago – how to generate large quantities of data as fast as possible and store it in a file. (As one could expect) I wrote a parallel solution using OmniThreadLibrary, more specifically the Parallel.ForEach high-level primitive. I’m not posting the complete solution here, just the important part – a method that accepts two parameters, requested file size and output stream, and generates the data. Actual initialization of data buffers is delegated to the FillBuffer method which you can see in the StackOverflow post.

Tuesday, September 06, 2011

Life after 2.1: Pimp My Pipeline

While the biggest focus on the Pipeline improvement was on the exception handling, there were also some changes in the basic functionality.

The most important (and code breaking!) change happened to the Input function, which was renamed to From. If you now want to pass a input queue to a pipeline, use pipeline.From(queue).

Second code breaking change happened to the Run function which now returns IOmniPipeline (i.e. the pipeline interface) itself, not the output blocking collection. Luckily, both changes will be caught by the compiler which would not want to compile the old code any more.

Thursday, August 25, 2011

Multithreading is Hard!

I have known for a long time that there’s a potential race condition between two writers in TOmniBlockingCollection but I thought that it doesn’t present and clear and present danger. Boy was I wrong!

Friday, July 29, 2011

Life after 2.1: Parallel.Join’s new clothes

Parallel.Join has started its life as a very simple construct.
class procedure Join(const task1, task2: TProc); overload;
class procedure Join(const task1, task2: TOmniTaskDelegate); overload;
class procedure Join(const tasks: array of TProc); overload;
class procedure Join(const tasks: array of TOmniTaskDelegate); overload;
Later it got an optional parameter of the IOmnITaskConfig type, but that didn’t change its simplicity. You called Join, it executed some code in parallel, and only when all code blocks completed its execution, your main thread would proceed by executing the statement following the Join call.
Then I started to think about handling exceptions (just as I did for the Parallel.Future) and somehow this simplicity didn’t feel right to me anymore. At the same time I got involved in a prolonged discussion with Антон Алисов (Anton Alisov) and together we defined new features that new Join would have to have.

Thursday, July 28, 2011

OmniThreadLibrary 2.1 hotfix

All users of the 2.1 release, please download this very important hotfix.

There was a nasty bug in OtlEventMonitor where FreeAndNil was called on a variable containing garbage from the stack. >:-(

Great thanks to [Антон Алисов] for finding the problem.

Thursday, July 21, 2011

Life after 2.1: Exceptions in Parallel.Future

The main focus in the next OmniThreadLibrary release is on exception handling in high-level constructs (i.e. the OtlParallel unit). The first one to get this support is Parallel.Future. Why? Simple reason – it has a well-defined point of interaction with the owner (the Value function) and only one background task, which makes exception handling easy to implement.
IOmniFuture<T> was extended with three functions.
  IOmniFuture<T> = interface
    procedure Cancel;
    function  DetachException: Exception;
    function  FatalException: Exception;
    function  IsCancelled: boolean;
    function  IsDone: boolean;
    function  TryValue(timeout_ms: cardinal; var value: T): boolean;
    function  Value: T;
    function  WaitFor(timeout_ms: cardinal): boolean;
  end; { IOmniFuture<T> }
Any exception thrown in the background task and not caught in the future-calculating code will be caught by the IOmniFuture<T> implementation. When a Value is accessed, this exception will be raised in the owner thread.

Wednesday, July 20, 2011

Life after 2.1: Async redux

OtlParallel unit defines four overloaded Async methods in OTL v2.1:

class procedure Async(task: TProc; taskConfig: IOmniTaskConfig = nil); overload;
class procedure Async(task: TOmniTaskDelegate;
taskConfig: IOmniTaskConfig = nil); overload;
class procedure Async(task: TProc; onTermination: TProc;
taskConfig: IOmniTaskConfig = nil); overload;
class procedure Async(task: TOmniTaskDelegate; onTermination: TProc;
taskConfig: IOmniTaskConfig = nil); overload;

As it turned out, two of them are not necessary anymore. Since the introduction of the taskConfig parameter, termination procedure can also be specified by setting taskConfig.OnTerminated.

Tuesday, July 19, 2011

OmniThreadLibrary 2.1

Yes, it is ready. Get the ZIP or check it from SVN.

If you’re following the trunk, do the update. You’ll actually get more than 2.1 as I’ve already merged in development branch with support for exception handling in Parallel.Future and Parallel.Join. Warning – those changes may break the code as two version of Parallel.Async were removed. Check the history.txt and documentation in OtlParallel.pas for more info.

This time you can also download full UML diagrams for OmniThreadLibrary, courtesy of Rich Shealer.

2.1 release should be mostly non-breaking, except for changes in OtlHook exception filtering mechanism and removed EXIT_EXCEPTION exit code (see below for more info).

I’d like to thank dottor_jeckill, Rico Krasowski, vcldeveloper and TOndrej, who helped make this release even more awesomer.

Saturday, July 16, 2011

Getting ready for OmniThreadLibrary 2.1

After a long long wait (sorry folks, due to events out of my control this release took many months longer that I expected) OmniThreadLibrary 2.1 is finally ready!

I’m just putting together change log, testing demos to see if everything is working as it should and so on … A day or two and it will be packed and ready to go. If you’re impatient, just go ahead and check out the current version from the SVN – all the code is already in there.

I have a small favor to ask, though. If you’re using OmniThreadLibrary in D2009 or D2010 – can you please make sure that all tests are included in the appropriate Tests.<version>.groupproj file (and create missing <project name>.<version>.dproj files in the process)? And send the changes to me, of course – my email address is in OTL source files. It would be best if you can leave a comment here if you choose to help me so that the work won’t be duplicated by other programmers.

Thanks in advance, that will really help me getting OTL out quickly. (Otherwise I have to set up a virtual machine and install D2009 and D2010 as I’m not using them for everyday work anymore.)

EDIT: D2010 projects and updated test group are now in the repository, thanks to [vcldeveloper].

EDIT: D2009 projects and updated test group are now in the repository, thanks to [TOndrej].

Saturday, June 25, 2011

Sleep Sort in OTL

I found Sleep Sort so ingenious (in the mad genius way) that I just had to implement it using the OmniThreadLibrary framework.

The code is now shorter than Serg’s original implementation and it’s … wait for it, wait for it … even faster! Twice as fast as the original, actually! Now that I call an improvement!

The code below carries not copyright nor copyleft and can be used in any occasion as long as you don’t blame me for getting fired or any other problems in your personal or professional life it may cause.

Friday, June 10, 2011

Lock-free vs. Locking: Rematch!

My article on lock-free vs. locking data queues was well-received but there were also some comments and complaints. To answer the critics (your comments were all very appreciated!) and to fix some issues with the previous test I’ve decided to stage a rematch.

New contestants

Both Iztok and Chris have provided me with new versions of their queue implementations. Iztok’s code was tuned a little and changed to use TOmniValue instead of TAnyValue for better comparison with TOmniQueue. Chris has created three different variants of his code.

Thursday, June 02, 2011

OmniThreadLibrary Needs YOU!

That is, if you are a C++Builder programmer and want to help an open source project.

image

The problem with OmniThreadLibrary and C++Builder is very simple – I’m not using it. (The C++Builder part, obviously.) Therefore I’m not checking for compatibility with C++Builder and I cannot fix the stuff if it doesn’t work. (In C++Builder.)

And now a user reported that the OTL doesn’t compile. In C++Builder. And I don’t know how to help him. With his problems. In C++Builder.

[BCC32 Error] DSiWin32.hpp(36): E2257 , expected

[BCC32 Error] DSiWin32.hpp(346): E2040 Declaration terminated incorrectly

[BCC32 Error] OtlCommon.hpp(305): E2238 Multiple declaration for 'TOmniValueContainer::Item'

[BCC32 Error] OtlCommon.hpp(304): E2344 Earlier declaration of 'TOmniValueContainer::Item'

[BCC32 Error] OtlSync.hpp(33): E2113 Virtual function '_fastcall IOmniCriticalSection::Release()' conflicts with base class 'IUnknown'

[BCC32 Error] OtlSync.hpp(74): E2113 Virtual function '_fastcall IOmniResourceCount::Release()' conflicts with base class 'IUnknown'

Is there a nice soul out there that can tell me how to fix the problem? (Or even better, who can make sure that the OmniThreadLibrary compiles with C++ Builder.) Your fixed will be gratefully imported into the main development branch and you’ll earn an eternal fame.

Thursday, May 26, 2011

Lock-free vs. locking

For the past few days I was running tests on three different queue implementations – one lock-free, one based on Delphi’s TQueue<T> and TMonitor and one implemented using critical section and linked list. For a good measure I’ve also thrown a blocking wrapper around the lock-free queue into the mix. [Mostly because I’m using it a lot (it has useful features for multithreading work) and I wondered how much time penalty it adds to my applications.]
During that time I’ve discovered a showstopper bug in TMonitor which practically made TSimpleThreadedQueue useless when using more than one reader. Still, I’m including partial results for that implementation too, as they provide a good comparison.

Tuesday, May 24, 2011

TMonitor bug?

When Chris Rolliston implemented a simple threaded queue class using TMonitor, I was quite ecstatic. Finally I will be able to compare my lock-free queue with a threaded implementation! (That’s something I wanted to do for a long time but I never found a willpower to write a locking queue.)
My elation continued while I was coding my test app and while I tested my own queue. And then I plugged in Chris’ queue and … everything went downhill :( Immediately, my test app started crashing. At first it looked like the bug was in Chris’ code, but when I enabled debug DCUs, debugger pointed to a very unlikely location – TMonitor. Unlikely because of two reason – because I know that Delphi people take quality to the heart and test the code and because I know Allen is an experienced guy who writes excellent code.

Sunday, May 15, 2011

TDM Rerun #17: Put It In A Tree

Hierarchical data appears everywhere and most of the time it must be rebuilt from simple non-hierarchical storage. Think about mail, news, CVS repositories and databases, not to mention groupware and chat forums. Trees are everywhere.

- Put It In A Tree, The Delphi Magazine 118, June 2005

This article dealt with thread sorting, an algorithm that takes a number of items connected with parent-child relationship and puts them into a tree so that they can be displayed in a nice structured way. The ideas and implementation are still perfectly valid.

Links: article (PDF, 82 KB), source code (ZIP, 241 KB).

Divide and Conquer (in parallel)

One of the latest additions to the high-level OtlParallel constructs, Fork/Join, was implemented just before ADUG 2011 and presented there for the first time. Shortly after the ADUG I improved the Fork/Join a little but then forgot to blog about it as I was busy implementing Parallel.Async and Parallel.TaskConfig. Sorry :(
Fork/Join helps you solve just one class of problems, but it is an important one – the problems that can be solved by so-called Divide and Conquer algorithm.
For deeper discussion of D&C, read the Wikipedia article linked above. What interests us is that D&C works by subdividing the problem. Instead of trying to solve the big problem, we divide it into many smaller problems and then we try to solve them. Those subproblems may again be too big and have to be subdivided even further. The process continues until the subproblems are small enough that they can be solved easily.
Of particular interest to us are D&C algorithms where subproblems can be solved in parallel.

Tuesday, April 26, 2011

Configuring background OtlParallel tasks

High-level OmniThreadLibrary parallelism (i.e. the OtlParallel unit) is great when you are running mostly independent parts of code but what can you do when you want to communicate with the main thread from a task?
A few weeks ago my answer would be along the lines of setting communication channel manually or dropping down to low-level parallelism (i.e. the CreateTask) but both are very complicated solutions. There was certainly a room for better solution.
Since the release 910, released on April 17th, OtlParallel contains much simpler way to configure tasks and to set them up for communication with the owner.

Sunday, April 17, 2011

Simple background tasks with OtlParallel

While there’s a simple way to execute one-shot background threads with the low-level OTL API (by calling CreateTask), there is no such high-level function in OtlParallel. At least, there wasn’t one until release 899 was committed to the SVN. (Incidentally, that happened 11 days ago but I was silent about it because I was working on another feature – TaskConfig – which will be completed “really soon now”.)
In short, Parallel.Async accepts an anonymous method, normal method or procedure (all of them must be without parameters) and executes it in a background thread. That’s all.