Jump to content

Fr0sT.Brutal

Members
  • Content Count

    2268
  • Joined

  • Last visited

  • Days Won

    46

Everything posted by Fr0sT.Brutal

  1. Fr0sT.Brutal

    Good practices with nested methods

    Nested methods are fine. Just place as many variables as possible after them to avoid side effects.
  2. Fr0sT.Brutal

    Step-by-step debugging exceptions

    AFAIK there's no way except breakpoint on catch block
  3. Check Awesome-Pascal list from my signature as well
  4. Fr0sT.Brutal

    news about the beta of 10.3.4

    And the next version should be Delphi 10 Wacken \m/
  5. Fr0sT.Brutal

    Rules for changing cursor to HourGlass and back

    IMO nowadays it's better to show modal progress window (or even make the process async)
  6. Fr0sT.Brutal

    On The Design Of Uses Clauses

    AFAIU, the only truly reliable way of detecting excess uses is removing each used unit one by one and try compiling. But even then there are possible false positives when something useful happens in unit's init section. Anyway I doubt this task is required frequently so slow process or some part of false positives is quite acceptable
  7. Hi all, I'm asking for advice. How do you deal with callbacks / events that are called in the context of bg thread? For example, there's a class that, say, performs archiving of data async-ly. It has input buffer and an event with a chunk of data it processed (suppose it doesn't store it but throws away to a caller immediately). And it starts a bg thread to process data. In result, OnProcessedData is called from that bg thread. type TOnDataProcessed = procedure (const Data: TBytes) of object; TСompressor = class constructor Create(const InputData: TBytes; OnDataProcessed: TOnDataProcessed); end; { TСompressor } constructor TСompressor.Create(const InputData: TBytes; OnDataProcessed: TOnDataProcessed); begin TThread.CreateAnonymousThread( procedure var ComprData: TBytes; begin repeat ComprData := Compress(InputData); OnDataProcessed(ComprData); // <-- callback from bg thread until Processed; end).Start; end; And if we create it with handler like usual... Compr := TСompressor.Create(Input, СompressorDataProcessed); procedure TForm1.СompressorDataProcessed(const Data: TBytes); begin Inc(Processed, Length(Data)); // <-- BANG! Access collision possible lblProcessed.Caption := IntToStr(Processed); end; So what's the best way to avoid such situations? I underline - it is a library class. We can't be sure it will be always used in GUI env - so PostMessage is not a reliable option. 0) Comments/documentation - not an option, if some info could be missed, it will be missed 1) Naming convention like OnDataProcessedBgThread: TOnDataProcessedBgThread - simple but just a hint/reminder for a class user. 2) Synchronize is not much more useful because it could lead to deadlocks and lowers performance. 3) PostThreadMessage? Will require message processing loop which is not trivial for main application thread 4) Store records for each callback call in class' thread-safe queue and consume from it by a timer? 5) Ideas?
  8. Fr0sT.Brutal

    Spring4d and Rio

    Is classic Open package > Build > Install way already obsolete? Just curious - what so specific in install process that it requires special installer? Btw, there's an effort to make a package manager for Delphi called Delphinus. I haven't tried it yet but it looks promising.
  9. Fr0sT.Brutal

    Resolve a uses clause unit path?

    1. Have IDE open that unit 2. Check its path 3. Profit )))
  10. Thanks to all who answered, sorry for late response. Docs are good but hardly ever being read from A to Z. Interface should be intuitive IMHO or at least give some hints. Very interesting regarding work queues. Have you got any shareable code to look at? What about Synchronize/Queue? I always tried to avoid it but see Emba have done pretty much in this area. Is it safe?
  11. Fr0sT.Brutal

    Refer to Form Control without using the Form unit?

    Well, I don't know your needs but I'd move special translation to the form itself so that translator wouldn't know anything specific about controls. Like Form.OnShow TranslateCommon(Self); TranslateSpecial1([Spec1Button, Spec1Label, ...]); TranslateSpecial2([Spec2Button, Spec2Combo, ...]);
  12. Faced the issue in my project. I have OnDataAvailable reading and processing data and OnSessionClosed logging the event and doing some other things. And in some cases server sends a response and then immediately closes connection. So I get: OnDataAvailable OnDataAvailable FD_CLOSE that calls OnDataAvailable and then OnSessionClosed The problem is that in OnDataAvailable I can't tell whether the socket has been closed or not because FCloseInvoked flag is set to True only after DataAvailable loop. I suggest (if that won't harm or change behavior) to set FCloseInvoked flag before DataAvailable loop and publish it as read-only property so that a user could distinguish whether he can expect some more data or not. For now I had to call processing method from OnSessionClosed as well.
  13. Angus, I have wsoReceiveLoop option set and before calling OnSessionClosed OnDataAvailable is being called anyway. In current state processing code should be extracted to separate method and called from both OnSessionClosed and OnDataAvailable, moreover it is likely to require SocketClosed parameter to decide whether there will be no data anymore or it could expect some.
  14. Fr0sT.Brutal

    Passing back a string from an external program

    Why inventing bicycles with triangular wheels when writing to STDOUT is a very simple method proven by decades? All *nix ecosystem is built on this mechanism. Executed app won't need anything more than WriteLn and executor app will have to intercept pipe handles.
  15. Fr0sT.Brutal

    Refer to Form Control without using the Form unit?

    Am I right that you in your TranslateProject method you have mentions of all translatable components from all forms in a project?
  16. Fr0sT.Brutal

    How to reliably know if there is data selected in TVirtualStringTree

    Some of these checks are senseless. Sender could not be nil. And you unlikely need GetFirst check unless you really use the first node not a focused one. In most cases, you only need one check for FocusedNode.
  17. Addition: if you have splitters or grid-style listviews with columns, save and restore their settings too
  18. Fr0sT.Brutal

    How do you organize units, forms?

    The same for me. 1) Form event handlers 2) Utilities (public/private methods) 2) Child controls' event handlers 3) Message handlers If there's pretty much code, I also put these groups into REGIONs It's a shame IDE autogeneration doesn't have an option to generate method name according to where it is declared
  19. Fr0sT.Brutal

    Using Continue in repeat statement

    repeat-until is slightly hard to realize construction because of its negative condition check. I use the following mnemonic: repeat stuff until condition is true.
  20. Fr0sT.Brutal

    On The Design Of Uses Clauses

    That's exactly the scheme I came to. I also avoid using units in impl. section except for app's forms.
  21. Method `OverbyteIcsHttpSrv.THttpConnection.ConnectionDataAvailable` contains following line: { We use line mode. We will receive complete lines } FRcvdLine := ReceiveStr; And below it is supposed that server have received HTTP-complete (ending with CRLF) line. But { Receive as much data as possible into a string } { You should avoid this function and use Receive. Using string will be } { much slower because data will be copied several times. } { ReceiveStr will *NOT* wait for a line to be received. It just read } { already received characters and return them as a string. } function TCustomWSocket.ReceiveStr : String; so a situation is possible when a chunk of header could be processed incorrectly or ignored. I suppose some kind of buffered line reader should be used.
  22. Sherlock, feel free to delete the topic completely 😉
  23. Yep, false alert, sorry. I was misleaded by that comment above TCustomWSocket.ReceiveStr and didn't notice that TCustomLineWSocket does all the necessary stuff incl. size check.
  24. I've never dealt with IPv6 but for me the purpose of this piece а code is to 1) assign v6 family from v6 IP address so that a user doesn't have to specify the family manually and 2) if IP is v6 check that OS supports it. And I'm not sure whether 2) is necessary, maybe it would fail later anyway on address resolution.
×