Lockless Multi-Threading in Delphi

Posted by on in Programming

In this video, I demonstrate a technique for communicating between threads in a Delphi application, without using typical locking mechanisms such as critical sections. Best Viewed in Full Screen (Recorded 1080p).

Download the source



Comments

  • Morten Lassen
    Morten Lassen Wednesday, 21 February 2018

    Thanks for this sample, Craig.
    It inspired me to implement something along those lines in one of my applications.

    I was wondering if you could clarify one thing for me:
    When do I use DisposeOf rather than FreeAndNil?

    Keep up the good work :)

  • Craig Chapman
    Craig Chapman Wednesday, 21 February 2018

    In modern versions of Delphi, you should switch to DisposeOf() always. DisposeOf exists to handle differences between the desktop compilers (without ARC memory management) and the mobile compilers (with ARC). Technically if your code will never be used on a mobile target, you don't need DisposeOf, but you never know when you might decide to Port to mobile.

  • Morten Lassen
    Morten Lassen Wednesday, 21 February 2018

    Cool!
    Thanks for clearing that up. I will definitely be using DisposeOf then :)
    /Morten

  • Craig Chapman
    Craig Chapman Wednesday, 21 February 2018

    It's true that the UI thread does both a push and a pull, but those operations are on two different arrays. The second thread is simply copying messages from the first array to the second. While I agree this is a very simple example, it demonstrates a two way communication between the UI thread and the other thread (consider it an echo thread). Perhaps this is the cause of confusion. The second thread need not simply echo the messages from one array to another, but instead could act on messages to do something useful. Echo was just the simplest example I could use.

  • Kim/Components4Developers
    Kim/Components4Developers Wednesday, 21 February 2018

    Hi,
    The problem is that its still not threadsafe. If one thread is pushing while the other is pulling then there is a race condition between updating and comparing the index counters.
    At least you should use InterlockedIncrement and when you reach a border and need to reset the index, you would need to use a waitloop and InterlockedCompareAndExchange which in itself introduce a finegrained lock.

    best regards
    Kim/C4D

  • Kim/Components4Developers
    Kim/Components4Developers Tuesday, 20 February 2018

    Hi. It seems to me that this article doesnt match its headline very well...
    In fact there is nothing multithreaded in it. You could just as well have created a TObject holding the dynamic array. Is something missing from the code sample?

  • Craig Chapman
    Craig Chapman Tuesday, 20 February 2018

    Two independent threads put messages into, and remove messages from a dynamic array, allowing communication between those threads. This happens without using locking mechanisms such as TCriticalSection. There is literally a descendant of TThread in the source.
    I feel this post precisely matches his headline.

  • Kim/Components4Developers
    Kim/Components4Developers Tuesday, 20 February 2018

    Hi, I maybe missing something... but the source showed one GUI thread entering the message, and another GUI thread (by the OnIdle event) pulling the message. The array is correctly owned by a 2nd thread, but that thread do not interact with the data at all as far as I could tell by glancing over the code :)

  • Kim/Components4Developers
    Kim/Components4Developers Tuesday, 20 February 2018

    I should rephrase it... one event run under the GUI thread entering the message and another event run under the GUI thread pulling the message.

  • Craig Chapman
    Craig Chapman Thursday, 22 February 2018

    FYI: If you re-watch the last 30 seconds, from time index 35:20, I explain what I just posted in my last comment. Note that the 'test thread' is a class derived from TThread - and note the difference between the 'InPipe' and 'OutPipe' properties. Messages go into the InThread and come out of the OutThread, they are copied from one to the other by the test thread execute method (so inside a second thread).

  • Craig Chapman
    Craig Chapman Thursday, 22 February 2018

    I think you're missing the second thread in the application. The GUI thread pushes a message into a ring buffer, where an aux thread pulls it, the aux thread then pushes that message into a second ring buffer, where the GUI thread pulls it off. There are two threads communicating with each other via ring buffers.

  • Please login first in order for you to submit comments
  • Page :
  • 1

Check out more tips and tricks in this development video: