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!

image

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.

image

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.

image

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!

image

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.

image

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

In response to my recent article on various kinds of initialization, GJ proposed another algorithm, which I will call here busy-wait initialization. This is the first time I’ve encountered this approach and I have no idea whether it is wide-known and has an “official” name.
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

Yanniel recently posted two ways to generate Fibonacci numbers, here are two more.

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.