Multithreading Made Simple with OmniThreadLibrary Primož Gabrijelčič
Introduction
OmniThreadLibrary is … … VCL for multithreading Simplifies programming tasks Componentizes solutions Allows access to the bare metal … trying to make multithreading possible for mere mortals … providing well-tested components packed in reusable classes with high-level parallel programming support … parallel programming today! “Why multithreading?” is most probably not a question anymore “Why not TThread?” is harder to answer - maybe a good answer would be “Because not CreateWindow”
Delphi 2007 and above; currently Win32 only Project status OpenBSD license Actively developed 1008 commits Actively used 2.0: 2710 downloads [in 7 months] 2.1: 1187 downloads [in 3 months] 2.2: current release, XE2 support Delphi 2007 and above; currently Win32 only
Add the OtlParallel unit to the uses list That’s all folks! Installation Download last installation from the Google Code or checkout the SVN repository code.google.com/p/omnithreadlibrary/ Add installation folder and its src subfolder to the project search path or Win32 library path Add the OtlParallel unit to the uses list That’s all folks!
Future Win64 FMX OS/X iOS?
OmniThreadLibrary basics
Task vs. thread Task is part of code that has to be executed Thread is the execution environment You take care of the task, OTL takes care of the thread
Communication TOmniValue = variant T/IOmniBlockingCollection = threadsafe queue with read-blocking behaviour Message/data passing can solve most synchronisation problems (shared data access, deadlocking)
High-level multithreading
Be afraid “New programmers are drawn to multithreading like moths to flame, with similar results.” -Danny Thorpe
Why high-level approach? Designing parallel solutions is hard Writing multithreaded code is hard Testing multicore applications is hard Debugging multithreading code is pure insanity Debugging multithreading code is hard Cross out off of this stuff – high-level primitives help you exactly with that
High-level multithreading Async start background task and continue Future start background calculation and retrieve the result Join start multiple background tasks and wait ParallelTask start multiple copies of one task and wait
High-level multithreading ForEach parallel iteration over many different containers Pipeline run a multistage process Fork/Join divide and conquer, in parallel Delphi 2009 required
Parallel.Async(code) Async Demo (probably HttpGet): async get and ignore result async with communication task.comm.send … async with invoke explain that this is better handled with Future
Future:=Parallel.Future<type>. (calculation); Query Future.Value; future httpget add termination handler show exception handling
Parallel.Join([task1, task2, task3, … taskN]).Execute Use Join to get three different pages with HttpGet explain exception handling
Parallel.ParallelTask.Execute (code) need a better demo
ParallelFor Parallel.ForEach(from, to).Execute( procedure (const value: integer); begin //… end) Parallel.ForEach(source).Execute( procedure (const value: TOmniValue); begin //… end)
ParallelFor Demo simple parallel for; nowait variant; ordered variant; maybe even aggregates Demo enumeration over different sources
Pipeline example Pipeline example: Simple read-compress-encrypt-write process For each doesn’t help here, both in compression and encryption process (may) depend on previously processed data What does R-C-E-W process really do? It consists of four parts, each processing data. Usually we don’t process complete data in each part before continuing into next. We can rewrite this code to use queues instead of fixed buffers. Why? … … Because now we can split those four parts into four threads. Threads execute overlapped. Total execution time (providing multicore machine) if much shorter.
Parallel.Pipeline([stage1, stage2, stage3]). Run “encryption” demo should work fine demo throttling explain exception handling
Fork/Join Divide and conquer QuickSort demo
Multithreading is hard?
Why high-level approach? Designing parallel solutions is hard Writing multithreaded code is hard Testing multicore applications is hard Debugging multithreading code is pure insanity Debugging multithreading code is hard Cross out off of this stuff – high-level primitives help you exactly with that
Questions?