Saturday, April 11, 2026

Introducing GpEventBus: Thread-safe event bus with synchronous event dispatch

TL;DR: Here is the documentation and here is the unit.

You probably know I do a lot of multithreaded programming😜 Quite a fun work with lots of fun problems, one of them being sending data across threads. OmniThreadLibrary uses queues and Windows messages for that but sometimes this is just not good enough.

Recently I was solving a problem of dispatching events across multiple threads. I have a UDP receiver that runs in a thread, does some processing (unpacks TS packets from the UDP) and sends unpacked data to receiver threads. I didn't want to use standard OTL messaging mechanisms for that as there are many packets received every second and Windows message queues would surely overflow.

I started working on a custom solution (something with a shared queue where the data is pushed and smart notification mechanism that is not triggered for every UDP packet) but then I got bored and I started thinking about a more general solution. I also wanted to move away from Windows messages as they require special work in the receiver thread. The general internet knowledge pointed me to Asynchronous Procedure Calls and an idea for a new implementation was born!

Wednesday, April 08, 2026

OmniThreadLibrary 3.08

Delphi 13.1 has exposed a long-present 64-compatibility bug in OmniThreadLibrary which is fixed in this release. Hopefully this was the last 64-compatibility bug in OTL :)

In other news, this release adds a TLightweightMREWEx extension to TLightweightMREW (Delphi 11+ only). Enhanced version supports nested BeginWrite/EndWrite calls. Read more in article Readers-writer lock - Part 4: Improving TLightweightMREW.

There were significant improvements to Locked<T>. On Delphi 11+ it uses TLightweightMREWEx internally (instead of a critical section). New methods (Delphi 11+ only) were added to support locking with read/write semantics: BeginRead, TryBeginRead, EndRead, BeginWrite, TryBeginWrite, EndWrite. On Delphi 11+,  Acquire/Release methods map to BeginWrite/EndWrite which preserves existing locking semantics. 

Locked<T> also got new access pair Enter/Leave and function IsInitialized. Original access function Acquire is implement as a procedure while new methods BeginRead/BeginWrite work as functions returning original type T. To mirror that, Enter also returns T (while Leave is just an alias for Release).

As a last modifidation, SetThreadName function from OtlCommon.Utils also calls SetThreadDescription Windows API if it is available. This allows logging code to log thread name even if they only know a thread handle by calling GetThreadDescription Windows API.

Download new version from GitHub!

GetIt will be updated soon.

Wednesday, March 04, 2026

Fixing Windows error 1400 in OTL tasks

From time to time I got error reports about "error 1400" in OTL and my response is always the same: "You are using it wrong." I never wrote anything about that, though. My bad :(

This time, however, I received an excellent error report with a minimal reproducible example (thanks!), which gave me an excellent excuse for this blog post ;)

Let me start with a little demonstration...

Saturday, January 17, 2026

Delphi and AI[10]: Coding GpTimestamp with Claude Code

A month ago I wrote a nice little unit that simplifies working with timestamps received from different sources - GpTimestamp - with help from Claude Code. Actually, to be fair - I took a backseat, set the goals, provided some info, and let Claude do all the work. I already wrote a post about GpTimestamp, but I said nothing about the coding experience. Let's fix that!