3.07.5: <<unreleased>>

- General improvements:
  - Reduced number of times NameThreadForDebugging is called when threadpool
    is used.
- Bug fixes:
  - [VyPu] fixed race condition in TOmniCriticalSection.Release which affected
    code that was using TOmniCriticalSection.LockCount.
  - OtlThreadPool did not respect OTL_DontSetThreadName define.

3.07.4: 2017-10-19

- Bug fixes:
  - TOmniEnumeratorProvider and TOmniValueEnumeratorProvider support
    dmoPreserveOrder option.
  - Fixed 64-bit issues in DSiWin32, GpLists, GpStringHash, and GpStuff.
  
- New features:
  - [VyPu] Locked<T>.Value is now both readable and writable property.  
  - Moved 'inline' functions around so that they will be inlined more often.

3.07.3: 2017-08-01

- Bug fixes:
  - Nasty thread-unsafe condition fixed in DSiWin32's DSiTimeGetTime64, which is
    used all around OmniThreadLibrary to measure small time intervals. 
- New features:
  - SetTimer accepts TProc and TProc<integer> timer methods.
  - IOmniTask implements method InvokeOnSelf which can be used to schedule
    anonymous function execution from a task back to self.  

3.07.2: 2017-07-05

- Potentially breaking change:
  - Cancel(taskID) will signal task's cancellation token before calling task's Terminate
    method. CancelAll will signal cancellation token for all running tasks before calling
    their Terminate method.
    Old behaviour (no CancellationToken.Signal before Terminate) can be achieved by
    calling overloaded version of the functions accepting the `signalCancellationToken`
    parameter or by setting IOmniThreadPool.Options to [tpoPreventCancellationTokenOnCancel].
- New features:
  - Added OnStop overload that accepts 'reference to procedure (const task: IOmniTask)'
    to Parallel.Join and Parallel.ParallelTask.
  - Added OnStopInvoke to all Parallel abstractions that implement OnStop method.
    - IOmniParallelLoop<T>.OnStopInvoke and IOmniParallelMapper<T1, T2> are only
      available on XE7 and newer compilers.
  - Added IOmniTaskConfig.NoThreadPool. This allows high-level abstractions to
    bypass thread pool entirely and run in 'non-pooled' threads.
  - TOmniCS.Initialize uses global lock to synchronize initialization instead of
    a CAS operation. This fixes all reasons for the infamous error
    "TOmniCS.Initialize: XXX is not properly aligned!".
 - Bug fixes:
  - Parallel.Future did not create task with the .Unobserved qualifier.
- New demos:
  - 66_ThreadsInThreads: Demonstrates how to manage OTL threads from other OTL threads
    and from TThread threads.

3.07.1: 2017-05-19

- New features:
  - Supports Delphi 10.2 Tokyo.
- Bug fixes:
  - Fixed long standing problem with timer processing in OtlTaskControl
    which could cause timers not to be triggered correctly and sometimes
    resulted in range check error.
  - Fixed potential problem in TOTPWorker.Cancel.
  - GParallelPool.IdleWorkerThreadTimeout_sec was incorrectly set to 60.000 seconds
    instead of 60 seconds.

3.07: 2017-02-16
- New features:
  - Added function IOmniPipeline.NoThrottle which disables throttling 
    on an entire pipeline or one of its stages.
  - Added function IOmniBlockingCollection.IsEmpty.
  - Added function IOmniBlockingCollection.Count.
  - Added readonly property IOmniThreadPool.NumCores which returns 
    number of cores this pool uses for running tasks. Changing Affinity, 
    ProcessorGroups, or NUMANodes properties may modify this value.
  - Communication subsystem handles ERROR_NOT_ENOUGH_QUOTA (1816) error.
  - Added function IOmniBackgroundWorker.OnStop.
  - Added property IOmniWorkItem.SkipCompletionHandler.
    - If it is set to True when work item is created or during its execution,
      request handlers for that work item won't be called.
    - If it is set to True in the OnRequestDone_Asy handler, then only
      OnRequestDone handler won't be called.
  - If ThreadDataFactory.Execute throws an exception, that exception is caught,
    ignored and ThreadData is set to nil. [issue #88]
- Bug fixes:
  - Reverted change from 3.06: "Any change to Affinity, ProcessorGroups,
    or NUMANodes properties will reset the MaxExecuting property."
    - New behaviour is compatible with the pre-3.06 code: Initially,
      MaxExecuting is set to Environment.Process.Affinity.Count.
      This value can only be changed by the external code, not inside the
      OtlThreadPool unit.
  - In threadpool, IdleWorkerThreadTimeout_sec and WaitOnTerminate_sec
    were initialized too late.
  - Fixed TOmniValue.CastTo<TArray<Int64>>. [issue #89]
  - If a future's cancellation token is signalled before the future is even
    created, the future worker is not started at all. [issue #85]
- New demos:
  - examples\folder scanner: File scanning example implemented 
    with a Pipeline.

3.06.2: 2016-10-24
- New features:
  - Implemented two-parameter version of Atomic initializer which 
    intializes an interface type from a class type.
- Bug fixes:
  - Programs using OtlCommon can be started on Windows XP.

3.06.1: 2016-10-19
- New features:
  - Implemented TOmniValue.Wrap<T> and .Unwrap<T>, a way to wrap anything
    (including TMethod and 'reference to procedure') in a TOmniObject.
    [Unwrap<T> must be called as follows: omnivalue.Unwrap<T>()]
- Bug fixes:
  - Fixed enum size enforcement in DSiWin32. [Could cause an application
    to crash if OtlCommon was used in the program.]

3.06: 2016-10-17
- Breaking changes:
  - Type TWaitFor.TWaitResult renamed to TWaitFor.TWaitForResult.
  - Packages were renamed. Now they are using $LIBSUFFIX scheme.
- New features:
  - Implemented Parallel.For<T>(const arr: TArray<T>).
  - New abstraction Parallel.TimedTask.  
  - Added types TOmniAlignedInt32 and TOmniAlignedInt32 which replaced
    TGp4AlignedInt and TGp8AlignedInt64.
  - Implemented Environment.ProcessorGroups and Environment.NUMANode to 
    provide information about processors in a massively parallel systems.    
    (Windows only, simulated on other platforms.)
  - Added NUMA support
    - Implemented IOmniTaskControl.ProcessorGroup and .NUMANode.
    - Implemented IOmniTask.SetProcessorGroup and .SetNUMANode.  
    - Implemented IOmniThreadPool.ProcessorGroups, .NUMANodes.
  - Implemented IOmniThreadPool.Affinity.
  - In the past, unhandled exceptions in the code handling the task execution
    were lost. Now, they are passed up to the IOmniThreadPool. If its property
    Asy_OnUnhandledWorkerException is set, exception will be passed to the event
    handler and application should react to it. The only safe way at that point
    is to log the error (and stack trace for the current thread) and terminate
    the application.
  - TOmniThreadPool.Create no longer waits on thread to be initialized. This
    allows a thread pool to be created inside DLL initialization code.
  - Implemented TOmniRecord<T>, a simple way to wrap "anything" in a record.
  - Added thread pool lifecycle notifications to OtlHooks 
    (RegisterPoolNotification, UnregisterPoolNotification).  
- Demos:
  - [HHasenack] Added more unit tests.
- Bug fixes:
  - Fixed unsafe 64-bit pointer-to-integer casts in TOmniCS.Initialize and 
    Atomic<T>.Initialize.
  - Fixed processing of 'new message'/'new wake event' events in TWaitFor.
  - [HHasenack] Fixed memory leak in handling 'owned objects' in TOmniValue.
  - IOmniAffinity.Mask changed from DWORD to NativeUInt to correctly support
    up to 64 processors on 64-bit systems.
  - Fixed memory leaks when iterating over interface types with Parallel.For.

3.05: 2015-09-07
- New features:
  - Added Delphi 10 Seattle packages and projects.
  - Setting IOmniThreadPool.MinWorkers property will start up idle worker threads 
    if total number of threads managed by the thread pool is lower than the new value.
- Bug fixes:
  - Fixed 'record' type handling in TOmniValue.FromArray<T> and TOmniValue.ToArray<T>.
  - Reimplemented support for > 60 worker tasks in the OtlThreadPool unit which 
    was removed from the code in 3.04a by mistake.
  - IOmniPipeline.PipelineStage[].Input and .Output are now always available
    immediately after the IOmniPipeline.Run.    
  - TOmniPipeline.Destroy calls TOmniPipeline.Cancel so a pipeline can be 
    shut down if user forgets to call Input.CompleteAdding.
  - When the code was waiting on less than 64 handles and timeout occurred, 
    the TWaitFor.Signalled[] property was not always empty.
  - TWaitFor was not working correctly with more than 64 handles if it was
    created with the parameter-less constructor.
  - TWaitFor.MsgWaitAny now uses RegisterWaitForSingleObject approach when
    waiting on 64 handles. Previously, MsgWaitForMultipleObjectsEx was called,
    which can only handle up to 63 handles.
  - Fixed pointer arithmetic in DetailedRTTI for 64-bit compilation.
  - Fixed: affinity mask in IOmniAffinity was only 32-bit wide on 64-bit platform.

3.04b: 2015-07-29
- New features:
  - Implemented TOmniSingleThreadUseChecker, a record which checks that the owner 
    is only used from one thread. 
  - TOmniCommunicationEndpoint.ReceiveWait and .SendWait are now fully thread-safe
    and support multiple consumers (former) and multiple producers (latter).
- Bug fixes:
  - Reimplemented support for TWaitFor in the TOmniTaskControl which was removed
    from the code in 3.04a by mistake.

3.04a: 2015-05-14
- New features:
  - Added XE8 packages and projects.
  - Tested with XE8.
- Bug fixes:  
  - DSiWin32
    - Fixed DSiClassWndProc parameter types for Win64.
    - DSiClassWndProc catches exceptions in instance's WndProc.
    - Fixed Affinity functions to work with up to 64 cores in 64-bit mode.
  - Added vtWideChar and vtPWideChar handling to TOmniValue.Create and .CreateNamed.
  - TOmniCS.GetLockCount won't crash if Initialize was not called yet.
  - Fixed Affinity functions in Environment to work with up to 64 cores in 64-bit mode.

3.04: 2015-03-01
- New features:
  - Implemented simple and fast Parallel.&For which supports only integer ranges.
  - Implemented Parallel.Map.
  - Added overloaded Execute methods to IOmniParallelInitializedLoop and
    IOmniParallelInitializedLoop<T> so that IOmniTask parameter can be passed
    to the executor.
  - Implemented Run overloads that internally call Invoke to start
    thread worker.
  - Implemented TOmniValue.HasArrayItem.
  - Implemented TWaitFor which supports waiting any/all and is not
    limited to 63 objects.
  - IOmniTaskControl can wait on any number of comm handles and wait objects.
    That enables support for >60 tasks in the OtlThreadPool. 
  - Implemented TOmniBlockingCollection.ToArray<T>.
  - NumTasks parameter (OtlParallel) can be negative. In that case, specified 
    number of cores will be reserved for other purposes and all other will 
    be used for processing.
    Example: If NumTasks(-2) is used when process has access to 8 cores,
    6 of them (8 - 2) will be used to run the task.  
  - Removed project groups.
  - Tested with 2007-XE7.
- Bug fixes:
  - Fixed race condition in IOmniPipeline termination code [tnx to Dean Hill].
  - Creating parameters with the array overload
    (IOmniTaskControl.SetParameters(['From', 0, 'To', 99])) was not working.
  - Fixed problems in demos 33_BlockingCollection and 47_TaskConfig.
- New demos:
  - 55_ForEachProgress: Demonstrates progress bar updating from a ForEach loop.
  - 56_RunInvoke: Simplified 'run & invoke' low-level API.
  - 57_For: Simple and fast parallel for.
  - 58_ForVsForEach: Speed comparison between Parallel.ForEach, Parallel.For, 
    and TParallel.For (XE7+).
  - 59_TWaitFor: Demo for the new TWaitFor class.
  - 60_Map: Demonstrates the new Parallel.Map abstraction.
  - 61_CollectionToArray: Demonstrates the new TOmniBlockingCollection.ToArray<T>
    method.

3.03a: 2013-10-21
- Bug fixes:
  - Fixed exception format string in TOmniValue.SetAsTValue [tnx to ring.nic].
  - Fixed deadlock when an empty list was provided to ForEach [tnx to ring.nic].

3.03: 2013-10-14
- New features:
  - Support for XE4 and XE5 (tnx to [Uwe Raabe]).
  - TOmniMREW is automatically initialized to 0 when created.
  - Implemented IOmniPipeline.PipelineStage[] property returning Input/Ouput collections
    of a specific stage.
  - Added IOmniTaskControl.Stop - signals thread to stop and immediately returns.
  - Added OtlSuperObject (tnx to [Lee_Nover]).
  - Different thread pool can be specified for all OtlParallel operations via the new
    TaskConfig.ThreadPool function.
  - Added IOmniLockManager<K> to the OtlSync unit.
    http://www.thedelphigeek.com/2013/04/threadsafe-lock-manager-1-design.html
    http://www.thedelphigeek.com/2013/04/threadsafe-lock-manager-2-code.html
    http://www.thedelphigeek.com/2013/04/threadsafe-lock-manager-3-test.html
- Bug fixes:
  - Fixed XE2/XE3 package compilation
  - TOmniBaseBounded(Queue|Stack) internally aligns allocated memory to required
    CAS granularity (8 bytes on 32-bit platforms, 16 bytes on 64-bit platforms)
    (tnx to [Alexander Alexeev]).
  - TOmniBaseBoundedQueue's ring buffers are internally aligned to 2*SizeOf(pointer)
    (tnx to [Alex Egorov]).
  - Prevent memory leak if (Queue|Stack).Initialize is called more than once
    (tnx to [h.hasenack]).
  - Fixed memory leaks in `forEach output` and `checkVat` examples
    (tnx to [Steve Maughan]).
  - Fixed TOmniTaskGroup.TerminateAll.
  - Simple pipeline stage handles exceptions in the executor function.
  - Compiles when 'Typed @ operator' is enabled (tnx to [arioch]).
  - Removed optimization which caused ForEach to behave differently on
    uniprocessor computers.
- New demos:
  - 54_LockManager: Demonstrates the new lock manager (IOmniLockManager<K>).

3.02: 2012-10-03
- New features:
  - Compiles with XE3.
  - Added XE3 packages and test projects.
  - Added Async/Await abstraction
    (http://www.thedelphigeek.com/2012/07/asyncawait-in-delphi.html).
  - Added OnStop overload to Parallel.ForEach that accepts
    'reference to procedure (const task: IOmniTask)'.
  - Added OnStop overload to Parallel.Pipeline that accepts
    'reference to procedure (const task: IOmniTask)'.
  - Implemented TOmniValue.IsRecord.
  - IOmniBackgroundWorker extended with task initializer (Initialize)
    and task finalizer (Finalize).
  - IOmniWorkItem extended with property TaskState.
  - Inlined bunch of TOmniWorkItem methods.
- Bug fixes:
  - Parallel.Join was broken if number of task to be executed was larger
    than number of threads. Thanks to [Passella] for reporting the problem.
  - Invalid 'joinState' was passed to the worker task in Parallel.Join if
    number of tasks to be executed was larger than the number of worker
    threads. Thanks to [meishier] for reporting the problem.
  - Fixed race condition in task teardown. Big thanks to [meishier] for
    putting together a reproducible test case.
  - ForEach finalizer is called if an exception occurs inside the ForEach task.
  - OtlParallel added to packages. Thanks to [Mason Wheeler] for reporting the problem.
  - OtlDataManager added to packages.
  - Fixed bug in TOmniTaskGroup.TerminateAll - maxWait_ms parameter was ignored.
    Thanks to [morlic] for reporting the problem.
  - Workaround for an internal error in D2009. Thanks to [ToHugie] for reporting
    the problem and to [Hallvard Vassbotn] for providing a fix.
    http://code.google.com/p/omnithreadlibrary/issues/detail?id=29
  - Fixed various scenarios where Invoke was not working. Thanks to [geskill]
    for providing report, test case and incremental testing on my partial solutions.
  - XE2 and XE3 design packages were referring to wrong runtime package (XE).
  - TOmniEventMonitor is marked as 64-bit compliant in XE2+.
    Thanks to [M.J. Brandt] for reporting a problem.
- Other changes:
  - Marked IOmniParallelLoop.OnMessage as deprecated (use TaskConfig.OnMessage).
- New demos:
  - 53_AsyncAwait: Demonstration of the new Async/Await abstraction.
- New examples:
  - ForEach output: Demonstrates how to 'flow' ForEach output directly into
    the main thread which immediately processes the data.
  - Twofish: Parallel implementation of the FishFacts demo.

3.01: 2012-04-21
- New features:
  - Exception handling added to Parallel.Async.
    http://www.thedelphigeek.com/2012/02/exceptions-in-async.html
  - Task property added to the IOmniWorkItem interface.
  - Added TOmniValueObj class, a class wrapper for TOmniValue record.
- Bug fixes:
  - Fixed race condition in InternalStop.
  - Fixed overloaded OnMessage declaration in the IOmniTaskConfig interface.
  - It was not possible to change timer delay once it was created.
    Big thanks to [Unspoken] for finding the bug.
  - TOmniValueContainer.Insert did not update internal 'count' field.
    Big thanks to [andi] for bug report and fix.
  - Internal event monitor messages must be processed in Terminate,
    otherwise OnTerminated is not called if the task is terminated from the task
    controller. Big thanks to [Qmodem] for finding the bug.
  - TOmniValue.CreateNamed was casting pointer to integer. 
    Tnx to [Mayjest] for finding the problem.
  - Fixed object and interface casting in TOmniValue.CreateNamed. 
    Tnx to [Mayjest] for finding the problem.
  - IOmniJoinState.Task was not correctly set in TOmniParallelJoin.Execute. 
    Tnx to [Mayjest] for finding the problem.

3.0 2011-12-30
- New features:
  - Support for 64-bit platform. Great thanks to [GJ] for doing most of
    the work!
  - Implemented background worker abstraction, Parallel.BackgroundWorker.
  - Implemented Atomic<T> class for lock-free initialization of interfaces 
    and objects.
  - Implemented Locked<T> class for locking intialization of practically 
    anything.
    http://www.thedelphigeek.com/2011/11/atomic-interface-initialization.html
    http://www.thedelphigeek.com/2011/11/per-object-locking.html
    http://www.thedelphigeek.com/2011/12/on-optimistic-and-pessimistic.html
    http://www.thedelphigeek.com/2011/12/creating-object-from-unconstrained.html
  - TOmniValue.AsInteger, AsString and AsWideString now work if the
    TOmniValue contains a Variant of the apropriate type.
  - TOmniValue can store arrays, hashes and records. Variant arrays are no
    longer used. IsArray tests it TOmniValue contains an array and AsArray 
    returns this internal container. Default indexed property still accesses 
    individual elements in this container. See demo 50_OmniValueArray for an 
    example.
    http://www.thedelphigeek.com/2011/11/tomnivalue-handles-arrays-hashes-and.html
  - Added a class which can wrap any record - TOmniRecordWrapper<T>.
  - Added an interface which can wrap any object and destroy it when the 
    interface goes out of scope - IOmniAutoDestroyObject.
- Bug fixes:
  - Fixed bugs in TOmniInterfaceDictionary which caused scheduled tasks not 
    to be destroyed until the program was terminated. Great thanks to 
    [Zarko] for providing a reproducible test case.
  - Fixed race condition between TOmniTask.Execute and TOmniTask.Terminate.
  - Under some circumstances ProcessMessage failed to rebuild handle
    array before waiting which could cause 'invalid handle' error.
  - Fixed wrong order in teardown sequence in TOmniTask.Execute which could 
    cause access violation crash. Great thanks to [Anton Alisov] for 
    providing a reproducible test case.
  - Fixed invalid "A call to an OS function failed" error in DispatchEvent.
  - TOmniMessageQueue.Enqueue leaked if queue was full and value contained 
    reference counted value (found by [meishier]).
  - Number of producers/consumers in TOmniForkJoin<T>.StartWorkerTasks was 
    off by 1 (found by [meishier]).
- New demos:
  - 49_FramedWorkers: Multiple frames communication with each own worker task.
  - 50_OmniValueArray: Wrapping arrays, hashes and records in TOmniValue.
  - 51_PipelineStressTest: Stress test by [Anton Alisov].
  - 52_BackgroundWorker: Demo for the new Parallel.BackgroundWorker abstraction.

2.2 2011-10-07
- New features:
  - Delphi XE2 support (Windows 32-bit only).
  - Parallel.Task can be used to execute multiple copies of a common code.
    [http://www.thedelphigeek.com/2011/09/life-after-21-parallel-data-production.html]
  - Breaking change! Parallel.Join reimplemented as IOmniParallelJoin interface
    to add exception and cancellation support. User code must call .Execute on the
    interface returned from the Parallel.Join to start the execution.
    [http://www.thedelphigeek.com/2011/07/life-after-21-paralleljoins-new-clothes.html]
  - Added exception handling to Parallel.Join. Tasks' fatal exceptions are wrapped
    in EJoinException and raised at the end of Parallel.Join method (or when WaitFor is
    called if Join is executed with the .NoWait modifier).
  - Added exception handling to IOmniFuture<T>. Tasks' fatal exception is raised
    in .Value. New function .FatalException and .DetachException.
    [http://www.thedelphigeek.com/2011/07/life-after-21-exceptions-in.html]
  - Two version of Parallel.Async (the ones with explicit termination handlers)
    were removed as this functionality can be achieved by using
    Parallel.TaskConfig.OnTerminated.
    [http://www.thedelphigeek.com/2011/07/life-after-21-async-redux.html]
  - Parallel.Join(const task: TOmniTaskDelegate) is no longer supported. It was
    replaced with the Parallel.Join(const task: IOmniJoinState).
  - Parallel.Join no longer supports taskConfig parameter (replaced by the
    IOmniParallelJoin.TaskConfig function).
  - Number of simultaneously executed task in Parallel.Join may be set by calling
    the new IOmniParallelJoin.NumTasks function.
  - Implemented TOmni[Base]Queue.IsEmpty. Keep in mind that the returned value may not be
    valid for any ammount of time if other threads are reading from/writing to the queue.
  - Implemented another IOmniTaskControl.OnTerminated overload acception parameterless
    anonymous function.
  - Implemented [I|T]OmniBlockingCollection.IsFinalized.
  - Parallel.Pipeline accepts 'simple stage' (for loop implemented internally).
    [http://www.thedelphigeek.com/2011/09/life-after-21-pimp-my-pipeline.html]
  - TOmniValue can natively store exception objects (AsException, IsException).
  - Implemented IOmniBlockingCollection.ReraiseExceptions. If enabled
    (default: disabled), [Try]Take will check if returned value for exception
    (TOmniValue.IsException) and if true, it will reraise this exception
    instead of returning a result.
  - Assertions are enabled in OTLOptions.inc - OtlContainers needs them.
- Bug fixes:
  - Event monitor in connection to the thread pool was totally broken. 
    (Big thanks to [anton alisov] for finding the problem.)
  - Fixed [Try]Add/CompleteAdding/[Try]Take three-thread race condition in
    TOmniBlockingCollection.
    [http://www.thedelphigeek.com/2011/08/multithreading-is-hard.html]    
- New demos:
  - 48_OtlParallelExceptions: Exception handling in high-level OTL constructs.    
  
2.1 2011-07-19
- New features:
  - Parallel.Async can be used to start simple background tasks.
    [http://www.thedelphigeek.com/2011/04/simple-background-tasks-with.html]
  - Parallel.ForkJoin - divide and conquer (fork/join) framework.
    [http://www.thedelphigeek.com/2011/05/divide-and-conquer-in-parallel.html]
  - OtlParallel tasks can be configured with Parallel.TaskConfig; you can also
    use it to communicated with the owner thread from the task.
    http://www.thedelphigeek.com/2011/04/configuring-background-otlparallel.html
  - IOmniTask[Control] can call Invoke method to asynchronously execute a block
    of code in the other thread.
    [http://www.thedelphigeek.com/2011/03/synchronize-comes-to-omnithreadlibrary.html]
  - Passes timer ID to timer proc if it accepts const TOmniValue parameter.
  - Support for non-silent exceptions removed.
  - Added property IOmniTaskControl.FatalExecption containing exception that was 
    caught at the task level.
  - Change signature for exception filters in OtlHook.FilterException.
  - IOmniTaskControl termination empties task message queue and calls appropriate
    OnMessage handlers.
- Bug fixes:
  - Fixed race condition in TOmniTask.Execute.
  - OtlParallel compiles in Delphi 2009.
  - OTL monitor message window could be used after it was destroyed.
  - Parallel.ForEach was never running on more than Process.Affinity.Count tasks.
  - OtlParallel pools are created on the fly - Otlparallel unit can be used from a DLL.
  - [dottor_jeckill] Bug fix: TOmniResourceCount.TryAllocate always returned False.
  - Enumerating over TOmniTaskControlList (for example when using
    IOmniTaskGroup.SendToAll) leaked one object.
  - Makes sure timers are called even if there's a constant stream of messages in 
    registered message queues.
  - Fixed exception handling in the thread pool.
- New demos:
  - 43_InvokeAnonymous: Demo for IOmniTaskControl.Invoke and IOmniTask.Invoke.
  - 44_Fork-Join QuickSort: QuickSort implemented with Parallel.ForkJoin.
  - 45_Fork-Join max: Selecting maximum element in an array using Parallel.ForkJoin.
  - 46_Async: Demo for Parallel.Async.
  - 47_TaskConfig: Demo for Parallel.TaskConfig.

2.0: 2010-12-10
- New high-level primitives (unit OtlParallel):
  - Improved parallel for (Parallel.ForEach).
  - Futures (Parallel.Future<T>).
  - Pipelines (Parallel.Pipeline).
- Added support for multiple simultaneous timers. SetTimer takes additional 'timerID'
  parameter. The old SetTimer assumes timerID = 0.
- IOmniTask/IOmniTaskControl:
  - ParamByName has been removed, use .Param[name: string].
  - Param returns TOmniValueContainter.
- IOmniTaskControl.OnMessage also accepts an object (message dispatcher; form, for example)
- TOmniValueContainer:
  - IndexOfName renamed to TOmniValueContainer.IndexOf.
  - New methods in TOmniValueContainer class: ByName, Count, Exists. New properties:
    Items[integer], Items[string] and Items[TOmniValue].
- TOmniValue:
  - Fixed memory leak when sending String, WideString, Variant and Extended values over
    the communication channel and when queueing them into TOmni[Base]Queue.
  - Implemented _AddRef, _Release, _ReleaseAndClear.
  - TOmniValue can be cast as Int64.
  - Implemented conversions to/from TValue (Delphi 2010 and newer).
  - Implemented constructor.
  - [scarre] Added TDateTime support.
- New classes and interfaces:
  - TOmniMessageQueueTee
  - IOmniCommDispatchingObserver
  - TOmniCounter, auto-initialized wrapper around the IOmniCounter
  - TOmniMessageID record, used internally to implement timers.
- TOmniThreadPool: ThreadDataFactory can now accept either a function or a method
  (but can be used only as a method - SetThreadDataFactory).
- TOmniEventMonitor: Message retrieving loop destroys interface immediately, not when the
  next message is received.
- TOmniTaskFunction renamed to TOmniTaskDelegate.
- Added function CreateResourceCount(initialCount): IOmniResourceCount.
- Renamed IOmniCancellationToken.IsSignaled -> IsSignalled.
- .dproj tests renamed to .2007.dproj.
- Added Delphi XE project files.
- Bugs fixed:
  - Thread pool was immediately closing unused threads if MaxExecuting was set to -1.
  - Ugly bugs in TOmniBlockingCollection removed.
- new demos:
  38_OrderedFor: Ordered parallel for loops.
  39_Future: Futures.
  40_Mandelbrot: Parallel graphics demo (very simple).
  41_Pipeline: Pipelines.
  42_MessageQueue: Stress tests for TOmniMessageQueue.

1.05a: 2010-03-08
- Bug fixed: TOmniTaskControl.OnMessage(eventHandler: TOmniTaskMessageEvent) 
  was broken.
- Bug fixed: TOmniTaskControl.OnMessage/OnTerminate uses event monitor 
  created in the context of the task controller thread (was using global 
  event monitor created in the main thread).
- Implemented TOmniEventMonitorPool, per-thread TOmniEventMonitor allocator.

1.05: 2010-02-25
- Big rename: TOmniBaseStack -> TOmniBaseBoundedStack,
  TOmniStack -> TOmniBoundedStack, TOmniBaseQueue -> TOmniBaseBoundedQueue,
  TOmniQueue -> TOmniBoundedQueue, IInterfaceDictionary -> IOmniInterfaceDictionary,
  IInterfaceDictionaryEnumerator -> IOmniInterfaceDictionaryEnumerator,
  TInterfaceDictionaryPair -> TOmniInterfaceDictionaryPair.
- Implemented dynamically allocated, O(1) enqueue and dequeue, threadsafe,
  microlocking queue. Class TOmniBaseQueue contains base implementation
  while TOmniQueue adds notification support.
- Implemented resource counter with empty state signalling TOmniResourceCount.
- New unit OtlCollection which contains blocking collection implementation
  TOmniBlockingCollection.
- IOmniTask implements Implementor property which points back to the worker instance
  (but only if worker is TOmniWorker-based).
- Implemented IOmniEnvironment interface and function Environment returning
  some information on system, process and thread.
- Implemented IOmniTaskControl.UserData[]. The application can store any values
  in this array. It can be accessed via the integer or string index.
- Implemented TOmniValue.IsInteger.
- Implemented IOmniCancellationToken, used in Parallel infrastructure and in
  IOmniTaskControl.TerminateWhen.
- IOmniTaskControl and IOmniTask implement CancellationToken: IOmniCancellationToken
  property which can be used by the task and task controller.
- IOmniTaskControl implements OnMessage(msgID, handler).
- Implemented Parallel.ForEach wrapper (Delphi 2009 and newer).
- Implemented Parallel.Join wrapper (Delphi 2009 and newer).
- Refactored and enhanced TOmniValueContainer.
- TOmniTaskFunction now takes 'const' parameter.
- Bugs fixed:
  - TOmniEventMonitor.OnTaskUndeliveredMessage was missing 'message' parameter.
  - Set package names and designtime/runtime type in D2009/D2010 packages.
- New demos:
  - 32_Queue: Stress test for new TOmniBaseQueue and TOmniQueue.
  - 33_BlockingCollection: Stress test for new TOmniBlockingCollection, also demoes
    the use of Environment to set process affinity.
  - 34_TreeScan: Parallel tree scan using TOmniBlockingCollection.
  - 35_ParallelFor: Parallel tree scan using Parallel.ForEach (Delphi 2009 and newer).
  - 36_ParallelAggregate: Parallel calculations using Parallel.ForEach.Aggregate
    (Delphi 2009 and newer).
  - 37_ParallelJoin: Parallel.Join demo.

1.04b: 2009-12-18
- [ahwux, gabr] Fixed Delphi 2010 Update 4 compatibility.
- [ahwux] Added missing task interface cleanup to OnTerminated in demo 18.

1.04a: 2009-12-13
- IMPORTANT: Fixed thread pool exception handling.
- Implemented IOmniTask.RegisterWaitObject/UnregisterWaitObject.
- Added demo 31_WaitableObjects: Demo for the new RegisterWaitObject/UnregisterWaitObject API.
- Current versions of 3rd party units included.

1.04: 2009-11-23
*** COMPATIBILITY ISSUES ***
  *** Changed semantics in comm event notifications! When you get the 'new message'
      event, read all messages from the queue in a loop!
  *** Message is passed to the TOmniEventMonitor.OnTaskMessage handler. There's no need
      to read from Comm queue in the handler.
  *** Exceptions in tasks are now visible by default. To hide them, use
      IOmniTaskControl.SilentExceptions. Test 13_Exceptions was improved to demonstrate
      this behaviour.
- Works with Delphi 2010.
- Default communication queue size reduced to 1000 messages.
- Support for 'wait and send' in IOmniCommunicationEndpoint.SendWait.
- Communication subsystem implements observer pattern.
- WideStrings can be send over the communication channel.
- New event TOmniEventMonitor.OnTaskUndeliveredMessage is called after the task is
  terminated for all messages still waiting in the message queue.
- Implemented automatic event monitor with methods IOmniTaskControl.OnMessage and
  OnTerminated. Both support 'procedure of object' and 'reference to procedure'
  parameters.
- Implemented IOmniTaskControl.Unobserved behaviour modifier.
- New unit OtlSync contains (old) TOmniCS and IOmniCriticalSection together with (new)
  TOmniMREW - very simple and extremely fast multi-reader-exclusive-writer - and atomic
  CompareAndSwap functions.
- New unit OtlHooks contains API that can be used by external libraries to hook into
  OTL thread creation/destruction process and into exception chain.
- All known bugs fixed.
- Current versions of 3rd party units included.
- New demos:
  - 25_WaitableComm: Demo for ReceiveWait and SendWait.
  - 26_MultiEventMonitor: How to run multiple event monitors in parallel.
  - 27_RecursiveTree: Parallel tree processing.
  - 28_Hooks: Demo for the new hook system.
  - 29_ImplicitEventMonitor: Demo for OnMessage and OnTerminated, named method approach.
  - 30_AnonymousEventMonitor: Demo for OnMessage and OnTerminated, anonymous method approach.

1.03: 2009-02-08
- Added support for per-thread initialized data to the thread pool.
- Communication between TOmniThreadPool and TOTPWorker is protected with a critical 
  section. That allows multiple threads to Schedule tasks into one thread pool.
- Removed OnWorkerThreadCreated_Asy/OnWorkerThreadDestroyed_Asy thread pool 
  notification mechanism which was pretty much useless.
- Added connection pool demo.

1.02: 2009-02-01
- Thread pool reimplemented using OmniThreadLibrary.
- Implemented IOmniTaskControl/IOmniTask.Enforced behaviour modifier.
- Implemented IOmniTaskControlList, a list of IOmniTaskControl interfaces.
- Added background file search demo.
- Implemented TOmniCS critical section wrapper.
- Fixed a bug in TGpStringTable.Grow and TGpStringDictionary.Grow which 
  caused random memory overwrites.
- Bug fixed: One overload of SetParameter was not returning Self.
- [Jamie] Fixed bug in TOmniTaskExecutor.Asy_SetTimerInt.
- [ajasja] Fixed bug in demos 4, 5, and 6. Exceptions was raised if demo app
  was closed without stopping the background task first.
- Updated to FastMM 4.90.
- Current versions of 3rd party units included.

1.01: 2008-11-01
- [GJ] Redesigned stack cotainer with better lock contention.
- [GJ] Totally redesigned queue container, which is no longer based on stack and 
  allows multiple reader.
- Full D2009 support; D2009 packages, project files and Tests project group.
- Invoke-by-name and invoke-by-address messaging implemented
  (http://17slon.com/blogs/gabr/2008/10/erlangenizing-omnithreadlibrary.html and
  http://17slon.com/blogs/gabr/2008/10/omnithreadlibrary-using-rtti-to-call.html
  and demos 18 and 19).
- CreateTask(reference to function (task: ITaskControl)) implemented (D2009 only).
- Blocking wait (ReceiveWait) implemented (demo 19).
- Added enumerator to the IOmniTaskGroup interface.
- Implemented IOmniTaskGroup.RegisterAllWithTask and .UnregisterAllFromTask.
- Added automatic comm unregistration for IOmniTaskGroup.RegisterAllCommWith.
- Implemented IOmniTaskGroup.SendToAll. 
- New/updated tests/demos:
  - 10_Containers 
    - 2 -> 2, 1 -> 4 and 4 -> 4 tests for stacks and queues, 
    - [1, 2, 4] -> [1, 2, 4] full tests.
    - Writes CSV file with cumulative test results.
  - 17_MsgWait: demo for the .MsgWait behaviour modifier.
  - 18_StringMsgDispatch: Invoke demo.
  - 19_StringMsgBenchmark: Invoke benchmark, ReceiveWait demo.
  - 20_QuickSort: Parallel quicksort demo.
  - 21_Anonymous_methods: Anonymous methods demo (D2009 only).
- Message ID $FFFF is now reserved for internal purposes.
- Better default queue length calculation that takes into account OtlContainers 
  overhead and FastMM4 granulation.
- Bug fixed: TOmniValue.Null was not really initialized to Null.
- Bug fixed: Setting timer interval resets timer countdown.
- Bug fixed: TOmniTaskControl.Schedule always scheduled task to the global 
  thread pool.
- Current versions of 3rd party units included.

1.0a: 2008-09-02
- TGp4AlignedInt from GpStuff.pas is supposedly D2006 compatible (says a reader) 
  so it has been enabled on that plaform. As a result, it is now possible to 
  compiled and use OTL in D2006 (said the same source).
- SpinLock.pas has been updated.
- Test 6 has been changed to show why one would want to use 
  IOmniWorker.Implementor function.
- FastMM 4.88 included in the repository to simplify debugging.
  FastMM4 was created by Pierre le Riche and is not covered by the 
  OmniThreadLibrary license. It is released under a dual licensed and you can use 
  it either under the MPL 1.1 or LGPL 2.1. More details in the included readme 
  file and on the FastMM4 home page.

1.0: 2008-08-26
- Initial release.