Jump to content

Dalija Prasnikar

Members
  • Content Count

    717
  • Joined

  • Last visited

  • Days Won

    62

Everything posted by Dalija Prasnikar

  1. Yes, I know. Situation where we had two different memory models that required slightly different coding patterns was unbearable. When people belittle ARC as memory management model, they tend to miss the fact that the problem with full ARC memory management was not the ARC as memory management model, nor the compiler itself, but the existing code that was not coded according to ARC rules. Hence the whole DisposeOf nightmare we had. Also, every memory management mode has good sides and bad sides. Each model is better for some use cases and worse for other.
  2. DisposeOf is needed solely for compatibility with existing code. Without maintaining compatibility and coding purely according to ARC rules, there would be no need for DisposeOf, too.
  3. I gave my reasons and arguments. I never said anyone has to agree with me. One thing is for sure. With ARC compiler that wouldn't have to care about compatibility with existing codebases there would be no Free nor FreeAndNil.
  4. Fair enough. I am saying that in some situations lifetime is beyond obvious, no matter what you use. Both in locally constructed instances and in instances with larger scope, regardless whether their lifetime is dynamic or not. But I have seen plenty of more complex code, where lifetime is not as clear cut and where there are thousand lines of code involved with multiple references (to different objects that are functionally intertwined). So FreeAndNil in destructor can make a difference between intended behavior and bugs, And the FreeAndNil might solve one bug only to make another one appear. Being able to categorize references based on intended behavior can make untangling such code an easier task. One thing is for sure. For you I don't doubt that you do know what particular code does. I may think that you are needlessly using FreeAndNil, but it will not make me think that your code is possibly bug ridden because you have no idea what you are doing. Unfortunately, that is generally not true and in plenty of code I have seen using FreeAndNil in "wrong" place was nothing comparing to the other coding horrors and bugs it contained.
  5. I am not that smart... I need all the help I can get... I cannot say for sure how would it work for my own code, which I know the best, because I don't use FreeAndNil everywhere. But this has definitely been a problem for me when reading other people's code. Or maybe that is just because it was overall not the best code ever written...
  6. I am talking about scenarios where object instances are lazily constructed or can be nil at some point for other reasons. For instance, think of list of children that is nil if there are no children and is only valid when child is added, but is also destroyed when last child is removed. In such case you would check if the instance is nil and construct the list before adding an new child. If you remove some child and there are no children left in the list, you would then call FreeAndNil on such list. If you are doing some processing on the children, you would just check if the list is nil and skip processing code in such case, because there are no children that need to be processed. So being nil is valid value for such reference and it can become nil at various stages during its owning instance lifetime. This is drastically different coding pattern than having some list which will be constructed in constructor and destroyed in destructor and will be valid reference in the rest of the code. For such references I would use Free and not FreeAndNil. This is the distinction of the code intent I am talking about. If you use FreeAndNil everywhere then you lose the intended design and usage. Of course, tehre are other ways to detect how the instance should be used, but nothing is a problem in simple code and scenarios. In more complex code losing the intent is much harder to deduct and it can mean the whole world of difference. I would say that you can solve that problem with leaving comments in the code, but I have yet to see such comments in code that indiscriminately use FreeAndNil. If I want to detect stale reference access I would use other tools, instead of relying on FreeAndNil. Yes, those are the two scenarios. And for the first one there are better tools, especially since FreeAndNil only nils one reference and you may have other stale ones. Yes, I have occasionally used FreeAndNil for detecting stale pointer access, but only as temporary debugging tool and because I was too lazy to setup FastMM for some reason (read not important project). In other words, I would replace it with Free when the code is fixed (I don't think I have ever used it for debugging purposes more than few times) I am not advocating that anywhere. That is why I am using Free (except for the second scenario with dynamically constructed objects), because I am not touching stale pointers, so using FreeAndNil is pointless.
  7. I was kidding. I don't even have to look at your code to know it is not thread-safe Like I said, using it for debugging purposes when something is off, and for some reason you cannot pinpoint the problem with other tools is fine. Problem is not in using FreeAndNil. It has its use case (beyond debugging purposes). The problem is using it everywhere, and then it obscures the intent of the code. When you FreeAndNil, your code is sending the different message that when you just Free. If you FreeAndNil that means such reference can be nil at any point and all code using such reference also needs to deal with scenario where reference is nil, either constructing new instance if the reference is nil, or skipping operations on nil reference. And that is drastically different code than one dealing with reference that cannot be nil.
  8. One question... you say you are using interfaces and then that calling FreeAndNil pointed you into right direction. Why are you calling Free (or FreeAndNil) on reference counted instance? If reference counting is disabled then the concept of strong and weak references is not applicable.
  9. How much you pay me to prove your Weak library is not thread safe Main problem with FreeAndNil supporters is that it is treated as silver bullet and it is not. Like @Stefan Glienke said, there are better tools for the job. And in multithreading scenario all bets are off. Of course, if you suspect something is out of order then you can add some help like calling FreeAndNil for debugging purposes. Been there, done that. But sprinkling them all over the code, just in case? Sorry, but that is hard no. It just pollutes the code and gives you false sense of security, because it will nil just one reference and all others will turn into dangling pointers. In other words, if FreeandNil can save me 70 hours of work in one case, it would still cost me way more work hours, when I have to read all code with FreeAndNil wondering whether there is a real purpose behind that call or it is there just for luck.
  10. I mean, it can always turn out to be mindless "use this... no use that..." fighting. But without knowing the facts around object construction and destruction process, it is impossible to have an argument based discussion.
  11. There is plenty to talk about. It is not just about FreeAndNil, but about constructing and destructing object and all the fine print around that process. While on the surface this topic seems simple enough and that there is nothing to talk about, it is rather complex topic and many developers, even experienced ones, easily forget about some very important facts around this topic that can cause serious issues in applications.
  12. 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
  13. Dalija Prasnikar

    ANN: Open Source Event Bus NX Horizon

    If you are already running it in a thread, then adding event bus on its own will not solve your problem. Even bus would help decoupling your code that is doing the search from the code that is showing the results, but it will not run faster. On the contrary. Since you are adding results to the UI, that part needs to run in the main thread. So you would use TThread.Queue or TThread.Synchronize. Event bus would call the same code in order to run event handler in the main thread. But when you do that you are calling it directly. Sending message through event bus runs a bit more code. You need to create message (event) which will cost some time, depending on the event type and the data it passes. Then sending message alone will lock the collection of subscribers, iterate through that collection, locate appropriate subscriber and then it will invoke event handler for that subscriber. And when iteration is completed it needs to unlock collection. So decoupling comes at some price. In most cases that price is well worth paying, because bus overhead is very small comparing to other code that runs, but it will definitely not run faster than some code that is directly wired and invoked. Why is your code having problems, is hard to say without seeing the code. Also, when you are searching on disk, performance will be tied with the content of the disk, and its hardware characteristics, as well as the whole system. For instance, if you try to access physically damaged part of the disk OS call may hang on such spot for minutes.
  14. Dalija Prasnikar

    ANN: Open Source Event Bus NX Horizon

    Thanks! I will try to add some. I will need some time to prepare some meaningful examples that can show potential use cases. Event bus is a messaging system. Delphi already has basic event bus implementation in System.Messaging https://docwiki.embarcadero.com/CodeExamples/Alexandria/en/System.Messaging_(Delphi) You can also look at the examples there as those use cases apply to my event bus, too. Main difference is that System.Messaging is not thread-safe and you can only use it to send messages in the context of the main thread. If you want to send messages across multiple threads you need a thread-safe event bus, like NX Horizon. Because, it is thread-safe, it also has some additional features like dispatching events (messages) asynchronously in the background thread. Maybe the easies way to explain what is event bus is comparing it to a Button OnClick event handler. When user clicks a button code in the OnClick event handler will run. main difference (besides multithreading support) is that with button and its event handler there is usually deeper connection and there is direct link with the button and its event handler. For instance if you click Help button on some form, you would want to open Help window from its OnClick event handler. But in that case your form with button needs to know about help form. If you have many forms that need to open help form will create tight coupling between all those forms and help form. With event bus, you can declare TOpenHelp event type and then you can subscribe some code to such event type. In your forms with help buttons, you would still need OnClick event handler, but instead of directly opening help form from that OnClick event you can send a message to event bus that TOpenHelp event happened. And then subscribers to that event (there can be more than one) will receive it and run the appropriate code in associated subscription event handler. This way your forms don't need to know about your help form, and code handling your help form does not need to know from where TOpenHelp came from. Event type also serves two purposes. Its type tells that particular event happened, and its content (event can be any automatically managed or value type) is used to pass additional data. for instance if the TOpenHelp is integer type, you use it to store and pass help page number depending on which help button is clicked and then you can open help on particular help page. Another example would be downloading some files in the background thread and then sending TDownloadCompleted event from that thread with some data about particular download and then subscribers can handle and do whatever they need to do with that data. Process it further, show it to the user, or anything else.
  15. Dalija Prasnikar

    ANN: Open Source Event Bus NX Horizon

    Thanks! There are few reasons why they are not implemented as of now. First, I wrote this for my own needs and in my code I used regular methods, so I didn't had immediate need for anonymous methods. Next, I wrote about this event bus in my recent book Delphi Thread Safety Pattern, so I wanted to keep code as minimal as possible and focused on bus itself. Anonymous methods are definitely one of the potential future enhancements, but I wanted to publish the code as soon as possible instead of waiting to polish it more as this might have postponed release indefinitely.
  16. Hi, I have just released new book: Delphi Thread Safety Patterns. https://dalija.prasnikar.info/delphitspatt/ It is on promotional sale until June,14. You can use Coupon Code: DTSPATT10 at checkout to get a $10 discount. At the moment there are two options: you can purchase eBook only or bundle: eBook and paper edition (those are separate purchases that go through different sellers and you will receive instructions for paper book with the eBook order). Paper book only on the Amazon is not available for the time being. Thank you all for the support!
  17. Are you sure it is executed in the context of the main thread? Because that is not what the stack trace says. It shows it is called from within TOutThread.Execute method. Anyway, whatever the problem is, there is not enough code to determine what is the root cause. Data modules can be constructed in the background threads, but only and only if all components used are thread safe in that regard. In other words if they support being constructed in background thread. How they are configured and what other components are linked as properties also impacts the thread safety. Additional comment. That application does not have memory leaks is good, but not having memory leaks does not mean that code is thread-safe and that it will run correctly.
  18. Dalija Prasnikar

    A book about Object Pascal Style Guide

    Being reserved word only means that you cannot use those words as identifiers. It does not tell you anything what each reserved word represents in the language. If you are asking about coding style and why is string written in small caps, then being reserved word has a meaning in that context because there is a coding style rule (which you don't have to follow, of course) that says reserved words are written in small caps. When you are talking about string being an alias for UnicodeString then this describes its semantic - its behavior and what it represents. "string" describes default string type and its definition can change in different compilers. For instance, in Delphi 1 string was alias to ShortString, and in Delphi 2 - Delphi 2007 it was alias for AnsiString, and since Delphi 2009 string is alias for UnicodeString.
  19. Dalija Prasnikar

    A book about Object Pascal Style Guide

    In Delphi string is separate data type and strings are not classes https://docwiki.embarcadero.com/RADStudio/Alexandria/en/String_Types_(Delphi) https://docwiki.embarcadero.com/RADStudio/Sydney/en/Fundamental_Syntactic_Elements_(Delphi)#Reserved_Words
  20. Dalija Prasnikar

    A book about Object Pascal Style Guide

    If you follow a guideline that all reserved words (keywords) are written in small caps, then string which is a keyword should be written as "string".
  21. Dalija Prasnikar

    How to increase the Delphi Editor line spacing

    QP report already exists https://quality.embarcadero.com/browse/RSP-34349
  22. Executing method on nil reference is actually a language feature. But such method must be static and you must not access any instance fields if instance is nil. One such method is TObject.Free that can be safely called on nil reference, because it checks whether object is nil before calling other code, in this case virtual destructor that cannot be executed on nil instance. procedure TObject.Free; begin if Self <> nil then Destroy; end; Additional explanation how static method dispatching works can be found here https://dalijap.blogspot.com/2021/07/virtual-methods-in-delphi.html
  23. Dalija Prasnikar

    Delphi 11.1 is available

    That is what I meant when I said all. We are on the same page here. That explains why I haven't bumped into that issue as I changed background settings for more than single theme, but I didn't do that all at once and changes were properly saved.
  24. Dalija Prasnikar

    Delphi 11.1 is available

    Hm.... it works for me. But there have been some glitches in saving various setting changes Since version 11. Saving same settings will randomly fail .
  25. Dalija Prasnikar

    Delphi 11.1 is available

    If by "option" you mean changing active theme an applying it in IDE, this is the wrong place. Dropdown with theme selection there will not change the theme, it is only a selector for setting background options for each available theme.
×