Posts

Showing posts with the label Delphi

Delphi 13.1 Update: Windows Arm64EC compiler

Image
The Delphi 13.1 update has just been released. One of the most significant new features in this update is the new 64-bit Windows ARM EC compiler. With ARM taking a strong foothold in desktop, laptop, and tablet computers, this is an additional Windows platform which can no longer be ignored. Now, if there is one thing that Microsoft does well, it is compatibility support for existing applications. Which means even your existing 32-bit and 64-bit Intel-based Windows applications will run on the Windows ARM OS. With that in mind, having a Windows ARM compiler at this time may not seem like a mission-critical feature, but this compiler still represents an extremely important milestone in Delphi's evolution. There are several reasons for that. First of all, Delphi developers are primarily Windows developers. Even if we support other platforms, Windows is and will always be our turf. Because Windows ARM EC supports both the VCL and FMX visual frameworks, no matter what kind of Delphi...

Delphi 12.3 Update

Image
The Delphi 12.3 update has just been released. The most exciting part of this release is the long-awaited 64-bit IDE. Now, this is only an Initial Release of the IDE, and it is not yet a full replacement for the 32-bit IDE and its functionality. The main advantage of the 64-bit IDE is that the available memory is no longer constrained by the 32-bit address space, and the upper limit is now the available system memory. The more you have, the more you can use. This is a great news for all developers with large projects, where the 32-bit IDE would easily hit the memory wall. To start with, the 64-bit IDE only supports the 64-bit Windows platform. The primary purpose of such a release with only partial functionality is to allow all component developers to update their design-time packages, and prepare them to support the 64-bit IDE. And to do that, you only need the 64-bit Windows platform anyway. For all other platforms, there is no immediate advantage of using a 64-bit IDE. As we all...

Celebrating 30 Years of Delphi With a New Book: Delphi Quality-Driven Development

Image
This year, on February 14th, Delphi celebrates its 30th birthday. Over the past three decades, Delphi has proven to be a robust and versatile development environment, empowering developers to build high-performance applications with ease across multiple platforms: Windows, Linux, Android, iOS, and macOS.  As we commemorate this milestone, I am also introducing a new book to help guide you into Delphi's fourth decade: Delphi Quality-Driven Development. Useful to lone developers and vast teams alike, this book aims to demonstrate a variety of essential practices and techniques for making high-quality, testable code. There is a 25% sale going on until the end of February for the Delphi Quality-Driven Development ebook, and there you can also get an additional discount on other books if you add them to your order. To all my fellow Delphi developers: May your code compile quickly, your memory be manageable, and your code testable.   Delphi Quality-Driven Development Book A practica...

Delphi 12.1 & New Quality Portal Released

Image
The Delphi 12.1 update has been released. Besides a number of bug fixes, this release also has a few new features. The most notable ones are the new Split Editor, which allows having multiple files opened side by side; and support for Android API 34. You can find more information about what is new in this update at https://docwiki.embarcadero.com/RADStudio/Athens/en/12_Athens_-_Release_1 However, the greatest change for all Delphi developers is a new bug tracking portal that replaces the old one, still available in read-only mode at https://quality.embarcadero.com/ . The new portal is hosted in Atlassian Cloud https://embt.atlassian.net/servicedesk/customer/portals  or through a redirect https://qp.embarcadero.com and is based on Jira Service Management (JSM), while the internal bug tracking system, which was also migrated to the cloud, was not changed and is running on Jira. This move to the cloud was inevitable, because Atlassian retired their Server line of products. JSM i...

Catch Me If You Can - Part II

It has been quite some time since I wrote the Catch Me If You Can post about the inability of LLVM-backed compilers to catch non-call hardware exceptions. In other words, hardware exceptions raised by code written in the same block as the try...except exception handler. Since then, more LLVM-backed compilers have been added to Delphi, and with those, more reasons to change common coding practices... but still, very few developers know about the issue. The original article covered only try...except exception handlers, and exploring what exactly happens with implicit and explicit try...finally handlers was left as an exercise to the readers and to some future, now long overdue, post. And Now: All Hell Breaks Loose When you read about non-call hardware exceptions not being caught by an immediate try...except block, the implications might not look too serious. After all, while plenty of code can raise exceptions, try...except handlers are not that frequently used in places, as mo...

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...

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...

Delphi Thread Safety Patterns book available on Amazon

Image
Delphi Thread Safety Patterns book is now available as paperback on Amazon, too.  https://dalija.prasnikar.info/delphitspatt/ While the thread safety of a particular piece of code depends on the surrounding context and how it is used, some data types are inherently unsafe, and for some of them, thread safety will depend on the use case and the specific code. Unfortunately, when you look at some class, type declaration, or API in isolation, there is very little information there that will tell you whether instances of that type can be safely used in multiple threads, or under which conditions. The proper place to learn about the thread safety of an API is its documentation. However, most documentation will not explicitly give you that information. Occasionally, the documentation will mention that a particular feature is not thread-safe, or will tell you that a feature can be used in background threads, but for the most part, you will have to figure out thread safety on your own. One...

FreeAndNil Debate: Thread Safety

One of the topics raised in yesterday's FreeAndNil debate was using FreeAndNil in multi-threaded code for avoiding access to a dangling reference when multiple threads are accessing and using the same object instance. Problem is that FreeAndNil is not thread-safe and cannot be used to achieve thread safety. You cannot call FreeAndNil on a shared object reference in one thread and then use if Assigned  in another to check whether object is still alive and then do something with that object. Your second thread can pass the if Assigned check and start working with the object while the first thread can destroy that object at any point. There is no mechanism in the FreeAndNil and if Assigned check that can prevent that. If you need to use shared object instance in such manner you need to use locking mechanism and lock all access, in all threads, to such an object. If you use locking mechanism, then you can use FreeAndNil in one thread and if Assigned check in another. I ment...

Book Review: Delphi Legacy Projects

Image
We are only few a years away from celebrating Delphi's thirtieth birthday. Because it has been here for quite some time, many Delphi projects are far from being brand-new, and almost every Delphi developer is or has previously worked on a project that can be considered a legacy project. Maintaining legacy projects is painful. Moving them to a newer Delphi version is even more so. A recently published book, written by Delphi expert William Meyer, "Delphi Legacy Projects", can help you ease some of that pain. It will guide the transformation of your legacy projects, help you bring them up to date, and make them more maintainable. Removing cruft, better organization, and less unit cycles can also significantly improve compile speed and IDE memory consumption. The book starts with an analysis of general problems in legacy projects and then presents strategies, one by one, that will help you tackle each individual problem. From project management issues, through dealing wit...

NX Horizon - Event Bus for Delphi

Image
 I have published initial release of NX Horizon Event Bus for Delphi as Open Source on GitHub. Features implements the publish/subscribe pattern, decoupling publishers and subscribers events are categorized by type any Delphi type can be used as an event supports four types of event delivery: synchronous, asynchronous, synchronous in the context of the main thread, and asynchronous in the context of the main thread provides generic record and reference-counted class wrappers for easier usage and management of existing types as events simple in both implementation and usage fast full thread safety https://github.com/dalijap/nx-horizon

Anonymous Threads: Use or Lose?

Anonymous threads are simple to use and are highly appealing when you need to quickly put and execute some small piece of code in a background thread. They work great when they run and complete, but if you have such a thread running when you close the application, all hell can break loose. The main cause of trouble with anonymous threads is self-destruction on completion. Because of that you cannot store a reference to such a thread and therefore you cannot wait for its completion during application shutdown. Other custom threads which have the FreeOnTerminate flag set to True also suffer from the same problem. During application shutdown, such self-destroying threads will keep running until they are just killed by the OS, because their owning process exited. This means they can be interrupted at any point during their execution, and they can access shared data long after that data has been destroyed during shutdown. If you want to avoid unexpected behavior and crashes during app...

Just released book: Delphi Thread Safety Patterns

Image
Delphi Thread Safety Patterns Book https://dalija.prasnikar.info/delphitspatt/ While the thread safety of a particular piece of code depends on the surrounding context and how it is used, some data types are inherently unsafe, and for some of them, thread safety will depend on the use case and the specific code. Unfortunately, when you look at some class, type declaration, or API in isolation, there is very little information there that will tell you whether instances of that type can be safely used in multiple threads, or under which conditions. The proper place to learn about the thread safety of an API is its documentation. However, most documentation will not explicitly give you that information. Occasionally, the documentation will mention that a particular feature is not thread-safe, or will tell you that a feature can be used in background threads, but for the most part, you will have to figure out thread safety on your own. One reason for this is that thread safety depends on t...

Are generics slow?

Image
In the TCoffeeAndCode session about "Code Profiling, Optimization, Performance, and Memory Leaks", it has been mentioned that generics are slow. However, no specific details were given, and this topic deserves to be explained in more detail before people start indiscriminately removing generics from their codebases, hoping to gain some speed. You can watch the session replay at: https://www.youtube.com/watch?v=hCFZv0I9TUk (minute 56) How generics work In order to understand how generics can impact speed, we need to know how generics work under the hood and why they are useful. The simplest way to explain generics is to imagine you have some particular code you need to run on different types. And to achieve that, you copy-paste the code and replace one type with another and nothing else. This is how generics work in C++, where they are not called generics, but templates. Instead of you having to copy-paste code and replace types, the compiler does that for you. Generic c...

Virtual methods in Delphi

Image
Virtual methods enable subtype polymorphism - in other words, they allow implementing different behavior in descendant classes. That means if you have a base TShape class with a virtual Paint method, and several descendant classes like TRectangle , TCircle and TTriangle , then each of those subclasses can implement a different Paint method to appropriately paint itself. You can call the Paint method on any shape instance without needing to know which kind it is, and it will be correctly painted. Static vs dynamic dispatch Virtual methods can achieve polymorphism via a mechanism called dynamic dispatching at runtime, while non-virtual methods will be statically dispatched (bound) during compilation. Polymorphism cannot be achieved by statically bound methods—in other words, when you call a statically bound method, you will call the same implementation for all descendant classes. Static dispatching means that the compiler will resolve the method address at compile time, and will...