Jump to content

Dalija Prasnikar

Members
  • Content Count

    1062
  • Joined

  • Last visited

  • Days Won

    91

Everything posted by Dalija Prasnikar

  1. Dalija Prasnikar

    I got bitten by an interface!

    As long as your variable is some interface type, reference counting will be properly initialized and you don't have to worry about memory management of Support destroying your instance. Code @David Heffernan posted for calling Support function is better one than your example. But this was not the root cause of your problems. You can also disable reference counting mechanism with the code @Alexander Elagin posted. In this case you have to Free the instance when you are done, but there is another catch, you need to make sure that at that point you don't have any active interface references to your object because automatic _Release that compiler inserts after that interface reference goes out of scope will access already destroyed object instance - which can lead to a crash.
  2. Dalija Prasnikar

    I got bitten by an interface!

    You are experiencing classic issue of "mixing objects and interfaces" Your TBaseFrame class has enabled reference counting and you are using it like normal class. You should store it in interface reference - fBaseFrame: IInterface (or whatever other interface type suits you the best) and you should not call Free on it (you cannot call it on interface, but point is that its memory will be automatically handled so you don't have to worry about it) https://dalijap.blogspot.com/2018/03/dont-mix-objects-and-interfaces.html
  3. Is attention to details useful? Yes. But also context matters. How useful is rearranging the chairs on Titanic?
  4. Dalija Prasnikar

    Cross-platform messaging system

    Gain with any messaging system is decoupling, so it makes sense to use it even if you make synchronous calls. But in multithreading scenarios, you need full fledged thread safe system capable of posting messages to a queue. In other words, asynchronous messaging. Anything else is just a crutch that can be used only in most simple scenarios.
  5. Dalija Prasnikar

    Cross-platform messaging system

    Yes, it can be harder to track from where message originated, but synchronous executing will make your thread wait twiddling thumbs while code runs in the context of the main thread. That is why posting messages is preferred. Of course, everything depends on the particular application and code and whether you can afford performance drop or not.
  6. How about http://docwiki.embarcadero.com/Libraries/Sydney/en/System.SyncObjs.TInterlocked.Exchange
  7. Dalija Prasnikar

    Add support for High-DPI gdiScaling

    You can call it whatever you like, but if the fact that MS didn't bother to update MDI window style to match their latest (now 5 years old) Windows 10 OS does not qualify as being deprecated, then I don't know what deprecated is. Also MS is spreading that FUD for the last 25 years...
  8. Dalija Prasnikar

    Add support for High-DPI gdiScaling

    In addition to what @David Heffernan said https://docs.microsoft.com/en-us/cpp/mfc/sdi-and-mdi?view=msvc-160
  9. Dalija Prasnikar

    Cross-platform messaging system

    Me, too. But complexities often come with additional features. And often simple systems do not have all the needed features, so when you need them, you can either write your own thingy that only has features you need, or you can use existing more complex one that has features you need plus some more.
  10. Dalija Prasnikar

    Cross-platform messaging system

    That is fine. Point is that System.Messaging is not thread safe. If you are writing multi-threaded application and you need to communicate using some messaging system, then System.Messaging will simply not work in such conditions. You can still use it to send messages to the main thread, but you need to synchronize messaging code, which is not always viable solution. In multithreaded applications, you will need thread safe messaging system that is also capable of posting messages to some message queue.
  11. Dalija Prasnikar

    Addendum to Martin Fowler quote

    Somebody needs to make a good compiler first...
  12. Me and my family are fine, now. Thanks!
  13. Not yet, as we have a backlog of other projects that piled up in the meantime. I had COVID and the earthquake hit the region again on December 29. None of this helped my keep my planned schedule. I do plan to release paperback eventually, but can't tell exactly when.
  14. Eh? Imagine how people who pay would feel if I start giving it away Anyway, if this would be bread and you would be hungry, I'd give you a loaf without thinking twice, but it's not. As much as I'd like to think it is, this book is not really something you can't live without, so... Sorry... And about hugs... My husband expressed his wish to have a private chat with you... you'd better lay low for a while
  15. The full list of code examples from the book Delphi Event-based and Asynchronous Programming is now available on GitHub: https://github.com/dalijap/code-delphi-async
  16. Dalija Prasnikar

    The Case of Delphi Const String Parameters

    I don't know if there is some other reason, but one reason is that with interlocked reference count you can freely use reference counted instances of any type (interfaces, dynamic arrays...) in multithreaded environment for read access if all threads have acquired their strong reference before original reference has been written to (cleared or assigned). In such case you don't need any other more costly locking protection, and you can share same string, so no copying necessary. Clearing such references when they go out of scope is thread safe, because memory deallocation will happen only in case where reference count reached 0. Also getting strong reference from strong reference (variable) held by thread is also thread safe - when I said held by thread it means that no other thread is allowed to write to that variable.
  17. Dalija Prasnikar

    The Case of Delphi Const String Parameters

    With this I agree... There is already solution for this bug - triggering reference counting mechanism for const references. Not other gimmick is necessary. I also said why this solution is not viable, because reference counting induces performance penalty. And this is exactly the reason why there is no reference counting trigger for const parameters so that developers have more control over reference counting and to speed up code execution, since in most code passing reference counting instance (regardless of the type) does not require reference counting. No reference counting is speed optimization. Yes, literal string could be initialized to some higher value. But then every time such string would trigger reference counting just like other strings do. But in this case reference counting would be triggered for string literals, and again that would introduce performance penalty for string literals that do not require memory management and reference counting. Comparing some integer value with -1 is inherently faster than increasing/decreasing reference count. Your proposal would again defeat the purpose of having -1 as speed optimization. We already have that. It is called ReferenceCount field in string header. We don't need another number, negative positive or whatever. http://docwiki.embarcadero.com/RADStudio/Sydney/en/Internal_Data_Formats_(Delphi)#Long_String_Types So your idea with negative flag would not work at all, but even if it would that would also require locking operation on reference count field and same performance penalty. It would be simpler to just trigger reference counting instead. Your idea with additional field (if I understood that correctly) would now mean we would have to do locking on two numbers instead of one. Again even more performance penalty. If we want to pay price in performance penalty, then we could just have compiler to omit all speed optimizations and be done with it. And again I think I explained well enough why this will not happen. Not everyone is willing to sacrifice speed because once in a blue moon some developers might shoot themselves in the foot.
  18. Dalija Prasnikar

    The Case of Delphi Const String Parameters

    Again, -1 is used JUST for string literals. You know when you write s := '123', then '123' is string literal and it is not dynamically allocated and its memory does not have to be managed. That is why there is optimization in RTL JUST for string literals that skips reference counting for them. -1 tells means you are dealing with string literal. You cannot use that value for any dynamically allocated data (strings).
  19. Dalija Prasnikar

    The Case of Delphi Const String Parameters

    Only nil pointer does not have any associated data. When you put some address in pointer you have associated it with some data that is not directly stored in variable itself. Since main purpose of pointer types is storing address to something, so if you treat that address as actual value, then you can say that raw pointers are value types. There is some ambiguity here, sure. In case of other reference types, you are definitely not interested in address as value, but content (value) in associated second part and that is what makes strings, interfaces, objects, dynamic arrays reference types.
  20. Dalija Prasnikar

    The Case of Delphi Const String Parameters

    Pointer is a reference type. But if you are bisecting reference types, then reference part (the immediate value stored in variable) has value type semantics. In other words when you assign one pointer to another you are creating copy of a stored value in that variable alone (reference part), just like when you are assigning one integer to another. If that pointer is not nil - then assigning one pointer to another will still point to the same data location, while pointer itself will have two distinct copies at that time. That also answers the first part of your question.
  21. Dalija Prasnikar

    The Case of Delphi Const String Parameters

    It works as expected because TFoo is record and records are value types. That means two things, first there is no additional memory management (heap) involved. s1 holds complete content of record on stack without indirections. Next because size of record does not fit into register and Value is passed as const compiler optimization kicks in and passes reference to s1 and not copy. In other words generated code is the same as it would be if you used var parameter. If you change declaration of TFoo and make it smaller, you would get different result, because Value would now contain independent copy of the data. TFoo = record X: byte; Y: byte; end; If you change declaration of Test to procedure Test(const [ref] Value: TFoo); Then regardless of TFoo size it would be always passed as reference (pointer) to the original data, and you would not have two copies.
  22. Dalija Prasnikar

    The Case of Delphi Const String Parameters

    That is because string literals don't require managing memory as they are part of the executable and are stored in data segment. Their reference count of -1 is just flag used for optimization and omitting reference counting that makes no sense for general reference counting mechanism.
  23. Dalija Prasnikar

    The Case of Delphi Const String Parameters

    I answered before thinking... so you got me But, real answer is more complicated. Technically, memory representation in Swift allows both variants depending on the size of data (content). So until you discuss actual code, there is not way of telling how will inner representation work. It may be value and it may be reference. In Swift value types and reference types in terms of Swift documentation also means all value types in Swift imply copy on assignment semantic, so for Swift developers that classification carries more weight than actual underlying representation - which again depends on the actual content. Also Swift compiler has(d) bugs around handling "value types" that are not really value types, but rather reference types in terms of Wikipedia definition, that would cause memory leaks under certain conditions (and other issues). I am saying bugs, because some of those I know about were actual bugs, I am not in position to say whether some of those bugs are just "as designed" behavior similar to Delphi const string parameter behavior. I am not that deeply involved with Swift and I am not familiar with all its internals, that also change every five minutes as Swift involves. Just like Delphi strings, Swift "fake" value types can suffer from some problems cause by the fact that they don't occupy single location in memory.
  24. Dalija Prasnikar

    The Case of Delphi Const String Parameters

    The only fact there is is that reference counting does not work like that. And it could not work with any bit flipping. Bit flipping does not solve anything. It is not a blasphemy, it is simply not a working solution. Again, I am not against discussing potential solutions to anything, nor how can something be improved, but when your initial understanding is flawed, there are just too many things that I would have to convince you about.
×