Jump to content

Primož Gabrijelčič

Members
  • Content Count

    246
  • Joined

  • Last visited

  • Days Won

    11

Everything posted by Primož Gabrijelčič

  1. Primož Gabrijelčič

    sample code for leanpub webinars?

    On http://www.omnithreadlibrary.com/webinars/ you'll find three links labeled "code". (And sorry for late reply, I was on a trip.)
  2. Primož Gabrijelčič

    Runtime Error on Closing with ScaleMM2 Memory Manager

    FastMM4 works perfectly and has no leaks as far as I know. We are using FastMM4 in Delphi applications that run 24/7 for years at the time and it works just fine. That holds for the latest FastMM from https://github.com/pleriche/FastMM4. I have no idea how built-in FastMM works. One should just be careful when running FastMM4 with /dFullDebugMode. In this mode, FastMM never returns memory to the operating system and your code can run out of memory. This is a feature, not a bug.
  3. Primož Gabrijelčič

    Runtime Error on Closing with ScaleMM2 Memory Manager

    Try to minimize the problem. Extract the problematic code from the application and try to reproduce. Or disable parts of the code which could relate to the problem and check if it went away.
  4. Primož Gabrijelčič

    Storing iomnifuture in dynamic array

    Provide a minimal working example, please.
  5. Primož Gabrijelčič

    Hands-On Design Patterns with Delphi

    Congrats! I'm still waiting on mine 😞
  6. Primož Gabrijelčič

    Delphi permutation code complexity

    If we are talking about time complexity (which is the usual case) and not space complexity, you can think about O() as telling you how slower your code will become if you increase the input size. Very roughly put, O(some_function_of_n) will make the code some_function_of_n slower if you increase the input by a factor of n. If your code needs M time to process m elements and you now run it on 20*m elements, O(1) will do that in time M, O(n) in time 20*M, O(n^2) in time 400*M, and O(log n) in time 4*M.
  7. Primož Gabrijelčič

    Delphi permutation code complexity

    The code needs max log(maxint) steps for the first and the second loop, max 9 steps for the third loop. As the integer size is constant for a given platform, this is just O(1).
  8. Primož Gabrijelčič

    RNG FizzBuzz

    Today I learned about pseudo random number generator driven FizzBuzz (https://stackoverflow.com/q/20957693) and I couldn't stop myself from porting it to Delphi ... program FizzBuzzRandom; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; procedure FizzBuzz(upTo: integer); var i: integer; begin for i := 1 to upTodo begin if (i mod 15) = 1 then RandSeed := 1973472511; Write(TArray<string>.Create(i.ToString, 'Fizz', 'Buzz', 'FizzBuzz')[Random(521) mod 4], ' '); end; end; begin FizzBuzz(100); Readln; end.
  9. Primož Gabrijelčič

    RNG FizzBuzz

    Just for the fun of it, here's a parallel version of FizzBuzz. No RNGs were abused this time. program ParallelFizzBuzz; {$APPTYPE CONSOLE} {$R *.res} uses Winapi.Windows, System.SysUtils, System.Classes; var GWrittenOut: TArray<boolean>; procedure FB(num: integer; output: string; extra: integer); begin TThread.CreateAnonymousThread(procedure begin Sleep(num* 1000 + extra); if not GWrittenOut[num] then begin Write(output, ' '); GWrittenOut[num] := true; end; end).Start; end; procedure FizzBuzz(upTo: integer); var i: integer; begin SetLength(GWrittenOut, upTo+1); for i := 1 to upTodo FB(i, i.ToString, 900); for i := 1 to upTo div 3 do FB(i*3, 'Fizz', 500); for i := 1 to upTo div 5 do FB(i*5, 'Buzz', 500); for i := 1 to upTo div 15 do FB(i*15, 'FizzBuzz', 100); end; var Msg: TMsg; begin FizzBuzz(20); while not GWrittenOut[High(GWrittenOut)] do while integer(PeekMessage(msg, 0, 0, 0, PM_REMOVE)) <> 0 do begin TranslateMessage(Msg); DispatchMessage(Msg); end; Writeln; Write('> '); Readln; end.
  10. Primož Gabrijelčič

    ANN: Parnassus Bookmarks and Navigator will be included in the next release of RAD Studio

    No, just this message box.
  11. Primož Gabrijelčič

    ANN: Parnassus Bookmarks and Navigator will be included in the next release of RAD Studio

    I'm getting this A LOT when right-clicking in the editor: --------------------------- Error --------------------------- A component named ParnassusAddBookmark already exists. --------------------------- OK --------------------------- Clean machine, fresh 10.3.1 install, no other Delphi, Bookmarks & Navigator installed via GetIt. @David Millington ?
  12. Yes, they work 🙂 (and why wouldn't they?). program RecursiveAnon; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; function MakeFib: TFunc<integer,int64>; var fib: TFunc<integer,int64>; begin fib := function (value: integer): int64 begin if value < 3 then Result := 1 else Result := fib(value - 1) + fib(value -2); end; Result := fib; end; begin var fib := MakeFib; for var i := 1 to 10 do Write(fib(i), ' '); Readln; end.
  13. Primož Gabrijelčič

    Recursive anonymous functions

    Of course it is! You can do this: for i := 1 to 10 do Writeln(MakeFib()(i), ' '); As Stefan noted on a side-channel, calling MakeFib causes a memory leak because the anonfunc interface now contains a cyclic reference to itself.
  14. Indeed, I got the "obvious" part from Hoare 🙂 The parallel part is all mine though. And I stand behind it. If one writes a unit test which tests the specification in full, it can in theory prove that a single-threaded unit complies with the specification. Throwing parallel processing in the mix, however, prevents us from even that result. At most one can say is that the unit probably works as expected inside one test environment on one computer.
  15. Indeed. In single-threaded code, good unit tests will show that the code obviously has no errors. In multi-threaded code, good unit tests will show that the code has no obvious errors. IOW, unit tests can only prove that your multi-threaded code doesn't work, not that it does.
  16. BTW, OmniThreadLibrary's TOmniBoundedQueue was implemented in 2008. Then we needed about a year to find few weird boundary conditions where the code would crash and fix them. After that the queue was working perfectly until 2018, when I found a race condition which caused the queue to say "sorry, can't add an item, the queue is full", when the queue has actually just become empty. Nobody noticed the problem in the meantime, we all thought the code is perfect, and the unit/stress test did not test for this specific scenario ... Writing lock-free structures is harder than you think. (Applies to me, too.)
  17. There's a Delphi version, too: http://deadlockempire.4delphi.com/delphi/
  18. As I said before, don't "believe" that the writer works ok - run tests!
  19. The writer also doesn't work. function TMWSRList.AddItem(pItem : Integer):Integer; var aOverFlow : Integer; begin Result := InterlockedIncrement(FWriteIndex); if Result >= MAX_SIZE then begin aOverFlow := Result - MAX_SIZE; { Reset FWriteIndex when it reaches MAX_SIZE } InterlockedCompareExchange(FWriteIndex, -1, MAX_SIZE + aOverFlow); Result := InterlockedIncrement(FWriteIndex); end; FItems[Result] := pItem; InterlockedIncrement(FAvailableCount); if Assigned(FOnNewItemAdd) then FOnNewItemAdd(self); end; FWriteIndex is at the end of array. Two threads call AddItem. Both threads increment FWriteIndex. Both threads enter `if`. Second thread executes InterlockedCompareExchange and InterlockedIncrement. That will skip slot 0 which will never be used, if I'm not mistaken. Plus - what use is InterlockedCompareExchange if you never test if the exchange was successful? Plus - the code doesn't work if the queue overflows (reader stops but writers keep writing). But that is by design, I guess?
  20. Aaaaah, single READER! Sorry, folks. That is such a weird concept (although, I admit, useful in some situations) that my brain autocorrected it into single WRITER. 🙂 🙂 Silly brain!
  21. Definitely doesn't work correctly. For starters, two parallel readers would clash horribly. If you want to implement lock-free structures, start by writing thorough stress-tests. They should run different scenarios - one reader, few readers, many readers ... very many readers (more than the number of cores in the system) - in a loop which runs for a long time (minutes, at least, preferably more). If you want to use something that is well-tested, take TOmniBoundedQueue from the OmniThreadLibrary.
  22. Primož Gabrijelčič

    GExperts Grep can use the MAP file

    Good one, thank you!
  23. Primož Gabrijelčič

    Communication between processes (IPC)

    @Jacek Laskowski, thank you for the correction. I will try to remember that in the future 🙂
  24. Primož Gabrijelčič

    Communication between processes (IPC)

    Alternatives: Named pipes, https://docs.microsoft.com/en-us/windows/desktop/ipc/named-pipes TCP/IP Network DDE, https://docs.microsoft.com/en-us/windows/desktop/ipc/network-dynamic-data-exchange Mailslots, https://docs.microsoft.com/en-us/windows/desktop/ipc/mailslots
  25. Primož Gabrijelčič

    Hands-On Design Patterns with Delphi

    A convenient timespace coordinate to get a copy of my book signed (or to buy a fresh new one 😉 ) Bergamo on 17th and 18th of April (https://conf.spring4d.com).
×