Jump to content

dummzeuch

Members
  • Content Count

    2699
  • Joined

  • Last visited

  • Days Won

    93

Everything posted by dummzeuch

  1. If I remember correctly (I bought Tomes of Delphi years ago), the source is not freely available. But it's a good idea, I'll have to check.
  2. Yes: I thought of improving it too, but it probably would be more work than writing my own. Just the fact that it's based on TStrings adds overhead that I would like to avoid. (I guess you meant THashedStringlist, because if I remember correctly, TStringHash isn't even exported.)
  3. What's the license of this code?
  4. Even if that was as easy as it sounds, I doubt that this meets the definition of "free implementation". Yes, this is what many people tell me. I might even drop some of them, but since I do most of my professional work with Delphi 2007 (the last pre Unicode version), dropping support for it in GExperts would not really be smart.
  5. You must keep in mind that Embarcadero only occasionally syncs the public jira with their internal one. Usually just before a new release lots of entries get closed. Unfortunately that does not always mean that they have been fixed.
  6. Everybody seems to be blogging about Delphi having been around for 25 years, so I won’t stay back and tell some of my story. When I finished university and started a job, Delphi was just about being “born” and I was working with Turbo Pascal and later Visual Basic. VB was great in some aspects because it allowed to easily design user interfaces and write code only where you needed it. It wasn’t after several years later that I was introduced to Delphi when I took a job at fPrint UK Ltd. (Yes, that’s what web pages looked in 1997) and moved from Germany to the UK. The time I worked there was among the best of my life. I had some great coworkers there who were expert software developers ... read on in the blog post.
  7. Which web page are you talking about? Mine? fPrint's? If it's the latter: I think it originally had a background color matching the GIFs' background, so it didn't look quite as bad as in the archived version.
  8. Given a class like this: type TMyClass = class private FSomeInstance: TSomeOtherClass; public constructor Create(_SomeInstance: TSomeOtherClass); destructor Destroy; override; end; [...] constructor TMyClass.Create(_SomeInstance: TSomeOtherClass); begin inherited Create; FSomeInstance := _SomeInstance; // other code here end; destructor TMyClass.Destroy; begin FSomeInstance.Free; inherited; end; Note: The class takes ownership of the TSomeOtherClass instance passed to it in the constructor. It frees it in its destructor. How would you write the code constructing it? My current code looks like this: SomeInstance := TSomeOtherClass.Create; try MyInstance := TMyClass.Create(SomeInstance); SomeInstance := nil; finally FreeAndNil(SomeInstance) end; The try..finally is there for handling the case where TMyClass.Create raises an exception, so there won't be a memory leak. But unfortunately the destructor is called even for partially created instances, so if the code after assigning FSomeInstance raises an exception, the instance of TSomeOtherClass would be freed twice. The only safe way I can think of would be to change TMyClass.Create as follows: constructor TMyClass.Create(var _SomeInstance: TSomeOtherClass); begin inherited Create; FSomeInstance := _SomeInstance; _SomeInstance := nil; // other code here end; If an exception gets raised in the inherited constructor (or in any other code before setting FSomeInstance) FSomeInstance would be nil, and _SomeInstance would be freed in the calling code. If it happens after setting _SomeInstance to nil, the destructor would free FSomeInstance and the calling code would not, becuse the var parameter was set to nil, which FreeAndNil (or even .Free) would detect. Of course, I could use Interfaces and rely on reference counting.
  9. I was assuming that this constructor should replace the one in my original example, where it was called from within a try finally block: constructor TMyClass.Create(_SomeInstance: TSomeOtherClass); begin inherited Create; // other code here FSomeInstance := _SomeInstance; end; If that's not the case, you have a memory leak if the inherited Create fails.
  10. dummzeuch

    TTimer equivalent with smaller interval

    The TTimer component has a minimum interval of 50ms. I understand that this is a limitation of the Windows timer which uses messages. What would be the alternative if I need smaller intervals, e.g. down to 10ms? The code is still supposed to be run in the main VCL thread. It doesn't matter if some events get lost because executing the code takes longer than the timer interval because the computer is busy. I just want to be able to get a smaller interval if the computer can support it.
  11. As Dalija said: Raising exceptions in the constructor is possible and even normal (e.g. TFileStream.Create for a file that does not exist or maybe is only temporarily not available). It's documented that the destructor must handle partly constructed objects. Allen Bauer blogged about this in 2006 (aparently he has removed his About Me page from the blog, or did it never have one?) But yes, many Delphi developers are not aware of this. I only recently (as in "a few years, maybe a decade ago") became aware of this issue and am still finding code that does not take this into account.
  12. That Wikipedia article links to an article by Thomas Wang Prime Double Hash Table from 1997 which explains what the point of choosing a prime number is. That sounds plausible to me, unless of course it is outdated by now due to different implementations of hash tables and hash functions.
  13. dummzeuch

    TTimer equivalent with smaller interval

    (Plus some kind of time interval checking.) No, but it's an interesting idea. Unfortunately not helpful in my particular case as I have now determined that it is not the timer interval but the code executed in the event that causes my slow down effect. I have tried to optimize it but so far failed. There are too many complex dependencies on multithreaded code to easily find the culprit.
  14. Oh, TDictionary is hash table based. I wasn't aware of that. In that case, of course it should be much faster for significantly large lists.
  15. You mean like this? SomeInstance := TSomeOtherClass.Create; try MyInstance := TMyClass.Create(SomeInstance); except FreeAndNil(SomeInstance) raise; end;
  16. I don't see how assigning the field as the last operation in the constructor would solve the problem of duplicate destruction. Yes, if there is an exception, the class' destructor won't free SomeInstance and leave that for the finally block. But what if there is no exception? Then the try..finally around the construction will free SomeInstance and leave a stale pointer to an invalid instance inside the class.
  17. What kind of difference do you mean here? Performance or readability?
  18. There are very rare cases where Destroy won't be called, but I would simply ignore them in this context. Hm, assigning FSomeInstance before calling inherited Create. I am so used to call inherited Create as the first thing in the constructor, I didn't think of this. Sounds promising. Of course that only works if the destructor itself works as expected with a partially created object which - looking at the real world code this is about - I think doubtful. But that's a different problem I'll have to fix anyway.
  19. How would DI (I guess you mean dependency injection) solve this problem? Can you please give an example?
  20. How can you be sure? As always: Nobody has found and reported a bug (yet).
  21. dummzeuch

    TTimer equivalent with smaller interval

    Some interesting implementations, thanks. Not sure that I can use any of them though.
  22. It all depends on the definition of "good code". Of course my code is good code. 😉 The advantage of code without comments is that you don't have to worry about the comments being wrong or outdated because the code was changed (fixed) and nobody bothered with the comments because the code compiles anyway. And of course there are those absolutely unnecessary comments like: // for all 50 entries for i := 1 to 50 do begin // process the entry process(entry[i]); end; // we are done processing all entries But some programmers (and managers) still insist that these kinds of comments are necessary and a sign of a well documented code base. I definitely disagree here. But I think we degress.
  23. I certainly am not a Delphi expert in the sense that I don't make mistakes and always produce perfect code. (And as I just yesterday noticed (again) some of my "knowledge" about Delphi is outdated or even has been wrong in the first place). So, I don't really qualify for answering this question even though I have been working with Delphi for nearly my whole professional life. But here goes anyway: I'm never done improving or fixing even my own code base. And don't get me started on the code base of the company I work for. We still have code that is at least 15 years old and has never been refactored even though it is in dire need for that. It's improving slowly but I doubt that it will ever be up to even my standards.
  24. dummzeuch

    TTimer equivalent with smaller interval

    Yes, I just found that too and was suprised. Apparently my "knowledge" about this minimum interval goes back to Windows 95 times. This also matches the logs that I am currently looking at: The next timer event starts in the same millisecond that the last one ended. So apparently it's not the interval that's the limiting factor here but the code executed in the event. Thanks everybody. That's the answer.
  25. dummzeuch

    Tool to fix up uses clause unit namespaces?

    GExperts has this functionality, but only for the current unit. Feel free to use that code to build a batch tool (it's not quite so easy since you must take the project settings and search paths into account). I'll accept patches, of course. 😉
×