Jump to content

Dalija Prasnikar

Members
  • Content Count

    1062
  • Joined

  • Last visited

  • Days Won

    91

Posts posted by Dalija Prasnikar


  1. If you are not dropping components on the form, then it is better that you pass nil as owner. That way you can use those components in background threads (please note that not all components are thread safe and can be used in the background, but in this case we are talking about Indy). Which is generally preferable when you are doing any kind of network operations.

     

    Having multiple try...finally blocks kills readability, so I prefer using only one. You need initialize references to nil, to avoid issues if construction fails somewhere in the middle and finally might call uninitialized pointer. 

     

      IdSMTP1 := nil;
      IdMessage1 := nil;
      IdSSLIOHandlerSocketOpenSSL1 := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
      try
        IdSMTP1 := TIdSMTP.Create(nil);
        IdMessage1 := TIdMessage.Create(nil);
        ...
      finally
        IdSSLIOHandlerSocketOpenSSL1.Free;
        IdSMTP1.Free;
        IdMessage1.Free;
      end;

     

     

    • Like 2

  2. 23 minutes ago, Yaron said:

    The entire threaded code is written within the canvas's lock section and works without any issues (font drawing and bitmap operations), except for the brush color which occasionally seems to use the wrong color.

    Brushes like other GDI objects need to be protected when shared between threads https://docs.microsoft.com/en-us/windows/win32/procthread/multiple-threads-and-gdi-objects

     

    I never worked with brushes in the background, so  don't know exactly how you should protect it. Answer is somewhere in Vcl.Graphics unit.

    • Like 1

  3. 16 minutes ago, IndexCon said:

    What I don't understand is that, every time a new version of MacOS appears we will have to recompile our application, this does not happen with Windows, I have an application compiled in 2001 that continues to work perfectly today, without the need to recompile. It forces us to buy MAC machines every so often and to pay for compiler updates.

    Apple does not value backward compatibility as much as Microsoft. They make breaking changes a lot, either in OS or their toolchain and that causes various issues. Some issues break application building process, some break applications. 

     

    • Like 1

  4. 1 hour ago, mvanrijnen said:

    This is a little odd in the installation notes:

     

    
    You must install the Adobe Flash Player ......
    
    

     

     

    because: Adobe Flash Player End of Life

     

    
    Since Adobe no longer supports Flash Player after December 31, 2020 and blocked Flash content from running in Flash Player beginning January 12, 2021, Adobe strongly recommends all users immediately uninstall Flash Player to help protect their systems.  
    
    

     

    Flash is not absolute requirement, but it is necessary for viewing interactive content when you generate modeling documentation.

    Still, it is obsolete technology and should be removed.

     

    https://quality.embarcadero.com/browse/RSP-32771


  5. 7 minutes ago, Carlo Barazzetta said:

    No, I didn't open a bug report because in my case it was just a demo of a component with on-the-fly style modification on the form itself to show how the component reacted with different styles.

    Well, if nobody reports issues, chances they will be fixed is zero to none. Yes, there is always chance that EMBT developers themselves will eventually bump into the issue and make internal report, but those chances are rather slim.

     

    I am not judging anyone here, reporting bugs takes time, but the more people report reproducible bugs they encounter, the less bugs there will be out in the wild. Yes, I also know that report alone does not mean that bug will be promptly fixed.

    • Like 1

  6. 16 hours ago, borni69 said:

    Would it be possible to have this TDictionary as a global variable shared by all threads  loaded on startup ? 

    If the dictionary is populated before threads start using it, and you are not writing anything afterwards, then you can safely share that dictionary between threads for reading without any additional protection. If you will be writing to it while threads are running, then you need to protect all reads and all writes with some locking mechanism.


  7. 12 hours ago, Mike Torrettinni said:

    I've been reading a lot about optimization and it's interesting to see that phrase 'premature optimization' is usually just a BS, except for extremely basic cases. I agree with this and by attempting some minor optimizations I learned how to optimize other bigger parts of the code.

    Problem with quoting is that usually it is either cut down to the point of being misquoting or it requires more context to be properly understood. Knuth is spot on, and if you read more besides the "Premature optimization is root of all evil" phrase, it will be more clear to you what it really means.  

     

    https://softwareengineering.stackexchange.com/questions/80084/is-premature-optimization-really-the-root-of-all-evil

     

    • Like 2

  8. 1 hour ago, Mike Torrettinni said:

    I noticed @DesadaptadoDimensional said he is learning Delphi, I guess in school.

     

    In Croatia (and Yugoslavia before separation) Pascal was taught in schools and universities. 

     

    There are still schools that have Pascal in their curriculum, but C and other languages are taking over.

     

    Whether or not Delphi was and is used somewhere, I don't know.  I only have information that FPC is used in some schools.

     

    CE licenses makes Delphi more approachable, so it is possible that this will change for the better.


  9. 14 minutes ago, Attila Kovacs said:

    @Bill Meyer the combo offer takes me to an only digital purchase page

    When you click on the combo, it explains that link will take you to the eBook, page and after the eBook purchase you will then receive link for purchasing paperback edition with discount. I guess you missed that part 🙂

     

    • Thanks 1

  10. On 1/14/2021 at 6:04 AM, Darian Miller said:

    Congrats!  Are you working on publishing a print version?  

    Paperback edition of the book has been released. There is 50% discount for paperback edition for everyone who buys eBook edition.

     

    If you have already purchased the eBook version, and wish to buy the paperback, you're also eligible for a 50% discount! You can find instructions at:

    https://dalija.prasnikar.info/delphiebap/index.html

    • Like 2
    • Thanks 1

  11. There have been changes in Windows that required updates to the applications. For instance UAC introduced with Vista. Occasionally, there are also some other tweaks in Window that can cause some "minor" issues and require code update.

     

    It is that Microsoft has really great track record of providing compatibility options for older applications, so even very old applications can keep running. but this is more Windows feature than Delphi one. It helps that Delphi mostly relies on very stable core WinAPI, and that it creates single executable. But on other platforms Delphi apps don't have such longevity.

    • Like 2

  12. 30 minutes ago, Rollo62 said:

    > Performance: That is the original issue you are solving.

     

    Not really, I was thinking in the direction that in 95% of cases have NO performance issue at all,
    so I could judge for "safety" over "performance".

     

    > There is no performance penalty here. You need to trigger reference counting when creating new instance. That is the original issue you are solving.

     

    You have misquoted me. I didn't say that original problem you are solving is performance, but that you should not worry about performance with using New because you cannot avoid initial reference counting trigger for reference counted instances. And original issue with const is that it does not trigger reference counting when creating object inplace.

     

    Performance comes to play, when you don't use const but in that case you don't have to bother using New either. Yes, there are other places where reference counting can bite you... but you can do whatever you like.

     

    30 minutes ago, Rollo62 said:

    Like

    1. Never use const interface parameters (in most cases where a little performance loss is acceptable)
    2. Always use local inside

    3. Keep as-is, educate on the issue

    4. Never use inplace-creation

    5. Always use .New creation approach

    That would make 1.) intrinsically safe under all circumstances, which was my goal, on cost of only a little performance loss.
    Well, that makes 4.) and 5.) still very valuable and preferrable, and working perfectly together with 1.) too.

    All in all reducing together the whole risk of "pitfalling" somewhere unexpected.

     

    Additional issue with 1. and 2. is that not all code is under your control. Education is the first thing you should do, regardless of other approaches. Keeping developers in "stupid" mode is never smart thing to do.

    • Like 1

  13. 15 minutes ago, Rollo62 said:

    So you mean "Never use inplace creation, no matter if its object or instance is used" ?

    Yes. Since such coding pattern is not too common in Delphi because of its manual memory management. So you either cannot use it at all, or you are creating objects and passing ownership which is not the most common scenario, or you are creating reference counted instance where inplace creating creates problems.

     

    15 minutes ago, Rollo62 said:

    The .New approach I like also a lot, and use it in many places.

    Yes, maybe thats solving issues, but also maybe has not 100% performance.

    There is no performance penalty here. You need to trigger reference counting when creating new instance. That is the original issue you are solving.

     

    15 minutes ago, Rollo62 said:

    The issue with all that I see is, it doesn't prevent or protect against accidentally using inplace creation,
    which the 1st solution would be able to solve.

    All you can do to prevent accidental misues is great, but sometimes people just need to use their brains and think what they are doing.

    • Like 4

  14. 21 minutes ago, Rollo62 said:

    What arguments are for the 2nd solution, are there any better ?

    I wouldn't use any of those solutions.

     

    21 minutes ago, Rollo62 said:

    I would vote for the 1., as a golden rule: DON't USE CONST ON INTERFACE PARAM's

    Because that is not golden rule. On the contrary, for reference counted types you would almost always use const to avoid unnecessary reference counting overheard.

     

    Problem is not in the method that has const, problem happens at call site. As such it should be handled at call site. First, handling it at call site allows you to trigger reference counting only for references that really need it, next, you will avoid situation where performance will become an issue and someone will go and change method signature according to common practice - using const and will inadvertently break code.

     

    Far better solutions than 1. or 2. are using additional variable instead of constructing instance during method call, This is also easy rule to remember - don't create anything inplace. 

    Next solution would be explicitly typecasting TFoo.Create as IFoo

    And the last one, I like the most because it prevents you to make reference counting mistakes in other code, too, is to have class function that will create instance and return it as interface reference.

     

    As for finding all places where you can create possible problem and you need to fix it, simple search and replace can go a long way. 

     

    For instance - if you have class function New, you can just replace TFoo.Create with TFoo.New and if have same parameter list, you are good.

    • Like 6

  15. 2 minutes ago, dkounal said:

    I had the same though, but:

    1. I can not reproduced it in any of my computers, nor inside the development IDE.

    2. It happens to a small number of computers of clients and in a couple of them it is reprodusable.

    3. I got this line of error from Eurekalog and I am not it is the correct line of the error

    I am testing now the cocinasync Tqueue<T>

    Random errors like that suggest that some of your code is not thread safe and originating point of your problems may not be in the place where it finally blows up, but it gives you some hints to inspect your code that uses ThreadedQueue in broader context and possible code paths before you land on the error.

     

    Using different queue will not magically fix your problem, because problem is not in TThreadedQueue but in your code. You might get different behavior, and it might crash more often or not, but it will not be fixed until you find and fix real issue.


  16. 2 hours ago, Anders Melander said:

    And there's a lesson in that.

    Yes, there is, but Delphi Praxis allows much broader questions than Stack Overflow. 

     

    So, while debugging questions here and there require same amount of information, algorithms generally don't fall into same category.

     

    I don't think that asking for some pointers and ideas is somehow not welcome here. How does it relate with Delphi... well, obviously implementation would be in Delphi.

    • Like 1

  17. 30 minutes ago, Remy Lebeau said:

    But then, I was looking at an older version (XE3).  Maybe things have changed in recent years?  Any comparison that avoids having to allocate new strings should be the fastest.

    Things changed since then... for some reason unknown to me StartsWith has been changed to the point it involves 10+ calls to other procedures, and eventually calls Windows API CompareString function. 

     

    Since the final call handles case insensitive variant, it makes sense in that case (still too many indirect calls for my taste), but code path for case sensitive variant is just WHY, OH, WHY????

     

    No wonder it is slower...

     

    I think the plain for loop comparing chars would do better...

    • Like 1
    • Thanks 1

  18. 41 minutes ago, Clément said:

    My class implements several interfaces, I want to check which interfaces are implemented and call the corresponding methods using some parameters. I wasn't expecting that Supports would also have this "side effect", although the documentation is clear about the destroying part...

    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.

    • Like 1

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

    • Like 2
×