Posts

Coming in Delphi 12: Disabled Floating-Point Exceptions

Delphi 12 is in the works. One of its small features that will have a huge impact is a change in the default handling of floating-point exceptions, which will now be masked on all platforms. Previously, floating-point exception handling was different across platforms, and most notably on the Windows platform: In VCL and console applications, floating-point exceptions were not masked and would raise an exception. On the other hand, FireMonkey applications had all floating-exceptions masked by default, regardless of which platform they were running on. Basically if you haven't explicitly changed the exception mask in your code to some value other than the default, and you had code that attempted to divide some number with zero, you would get an EZeroDivide exception in previous Delphi versions on the Windows VCL application. In Delphi 12, there is no exception, and the result of such a division will be +INF . So the following code will no longer raise an exception. If you were r

Beware of loops and tasks

Loops and anonymous methods don't go hand in hand. Any variable that changes for each iteration will cause problems if it is used within an anonymous method. I explained the mechanism behind variable capturing in the post Mysterious Case Of Wrong Value , along with the problem it causes with loops and its solution. Commonly, anonymous methods are used as callbacks or event handlers, where there are no loops in the context where variable capture happens. While there is a possibility to have an unexpected—wrong—value in such scenarios, it is rather easy to debug them and understand the order in which some code is called, and why the captured value is wrong in a given place. With the rise of multi-threading usage, and especially the Parallel Programming Library and tasks, writing anonymous methods inside a loop becomes more common, and it is much easier to write code where a captured variable will have the wrong value. The biggest problem with such code is that it will be harder to

Assigning result to a function from asynchronous code

One of the more common problems that comes up in multi-threading, especially when refactoring existing code, is assigning a result obtained from asynchronous code. In other words, how do you write a function that will return some value, and calculate that value in a background thread? Basically, converting the following code: function GetData(...): string; var Data: string; begin Data := LongTask(...); // assign result of a long-running task to a function Result := Data; end; To this one: function GetData(...): string; var Data: string; begin TThread.CreateAnonymousThread( procedure begin Data := LongTask(...); end).Start; // assign result of a long-running task to a function Result := Data; end; Now, the above code will compile, but it will not achieve the desired functionality. Even if we ignore its thread safety issues (the background thread writes to the Data variable and that can interfere with assigning it to the function result), the funct

DelphiCon 2023: NX Horizon - The Open Source Event Bus for Delphi Replay

Image
 Did you miss the DelphiCon session on "NX Horizon - The Open Source Event Bus for Delphi"?  The webinar replay is now available!  Code can be found on GitHub: https://github.com/dalijap/nx-horizon Replay can be found at:  https://www.youtube.com/watch?v=axu53AatjHc

CodeRage 2022: Challenges of Multi-threaded Programming

Image
Here you can find slides from my CodeRage 2022 presentation about Challenges of Multi-threaded Programming , as well as additional links to code examples related to the presentation. Slides: https://dalija.prasnikar.info/dl/DP_CodeRage2022.pdf Additional links: Thread-safe Event Bus: https://github.com/dalijap/nx-horizon Books: Delphi Event-based and Asynchronous Programming: Code Examples: https://github.com/dalijap/code-delphi-async Book: https://dalija.prasnikar.info/delphiebap/ Delphi Thread Safety Patterns: Code Examples: https://github.com/dalijap/code-delphi-thread-safety Book: https://dalija.prasnikar.info/delphitspatt/ Delphi Memory Management: Code Examples: https://github.com/dalijap/code-delphi-mm Book: https://dalija.prasnikar.info/delphimm/ Replay of the presentation can be found at:  https://www.youtube.com/watch?v=d4QTRXVj8mg

Zeroing Weak Object References

In the two-part post series, The purpose of weak references - Part I and The purpose of weak references - Part II , I wrote about the purpose of weak references in automatic reference counting, as well as in manual memory management, where they are commonly referred to as non-owning references. In ARC, object references to reference-counted objects are unsafe, non-zeroing weak references, and in manual memory management, non-owning references to an object instance are also unsafe. Unsafe, in the above context, means that you can safely use such references only if the object instance they point to always has a longer lifetime than the unsafe reference, or that there is additional mechanism (code) that will notify you when the object is destroyed, so you know the reference is not pointing to a valid object anymore. In manual memory management, TComponent implements such a notification mechanism. However, there are two downsides: first, it only works with TComponent descendants; and

The purpose of weak references - Part II

Image
In the first part of this post series, I covered owning and non-owning references under manual memory management, and the purpose of non-owning (weak) references in that memory model. Following the same use cases, we can now clearly show the purpose of their counterparts under the automatic reference counting memory model. Automatic reference counting Automatic reference counting is a memory model under which an object instance will be valid as long as there is at least one strong reference to that object instance. When the last strong reference goes out of scope or is nilled, the object's reference count will drop to zero, and the instance will be automatically destroyed. One of the side-effects of that design is that two object instances that are no longer reachable through any outside references can hold strong references to each other, thus keeping themselves alive and creating memory leaks. This is called a reference cycle. To prevent problems with reference cycles, ARC h