-
Content Count
247 -
Joined
-
Last visited
-
Days Won
11
Everything posted by Primož Gabrijelčič
-
Handle parallel.foreach exception
Primož Gabrijelčič replied to alr1976's topic in OmniThreadLibrary
Please start a new topic. -
Handle parallel.foreach exception
Primož Gabrijelčič replied to alr1976's topic in OmniThreadLibrary
To quote "the book": http://www.omnithreadlibrary.com/book/chap06.html#highlevel-foreach-exceptions -
sample code for leanpub webinars?
Primož Gabrijelčič replied to Chris Were's topic in OmniThreadLibrary
On http://www.omnithreadlibrary.com/webinars/ you'll find three links labeled "code". (And sorry for late reply, I was on a trip.) -
Runtime Error on Closing with ScaleMM2 Memory Manager
Primož Gabrijelčič replied to RussellW's topic in OmniThreadLibrary
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. -
Runtime Error on Closing with ScaleMM2 Memory Manager
Primož Gabrijelčič replied to RussellW's topic in OmniThreadLibrary
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. -
Storing iomnifuture in dynamic array
Primož Gabrijelčič replied to Rustam Novikov's topic in OmniThreadLibrary
Provide a minimal working example, please. -
Hands-On Design Patterns with Delphi
Primož Gabrijelčič replied to Primož Gabrijelčič's topic in Tips / Blogs / Tutorials / Videos
Congrats! I'm still waiting on mine 😞 -
Delphi permutation code complexity
Primož Gabrijelčič replied to Roberto Dall'Angelo's topic in Algorithms, Data Structures and Class Design
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. -
Delphi permutation code complexity
Primož Gabrijelčič replied to Roberto Dall'Angelo's topic in Algorithms, Data Structures and Class Design
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). -
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.
-
RNG FizzBuzz
Primož Gabrijelčič replied to Primož Gabrijelčič's topic in Algorithms, Data Structures and Class Design
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. -
ANN: Parnassus Bookmarks and Navigator will be included in the next release of RAD Studio
Primož Gabrijelčič replied to Dave Millington (personal)'s topic in Delphi Third-Party
No, just this message box. -
ANN: Parnassus Bookmarks and Navigator will be included in the next release of RAD Studio
Primož Gabrijelčič replied to Dave Millington (personal)'s topic in Delphi Third-Party
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 ? -
Recursive anonymous functions
Primož Gabrijelčič replied to Primož Gabrijelčič's topic in Algorithms, Data Structures and Class Design
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. -
Lockfree approach on a Single reader, Multiple Writer queue
Primož Gabrijelčič replied to kokoslolos's topic in Algorithms, Data Structures and Class Design
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. -
Lockfree approach on a Single reader, Multiple Writer queue
Primož Gabrijelčič replied to kokoslolos's topic in Algorithms, Data Structures and Class Design
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. -
Lockfree approach on a Single reader, Multiple Writer queue
Primož Gabrijelčič replied to kokoslolos's topic in Algorithms, Data Structures and Class Design
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.) -
Lockfree approach on a Single reader, Multiple Writer queue
Primož Gabrijelčič replied to kokoslolos's topic in Algorithms, Data Structures and Class Design
There's a Delphi version, too: http://deadlockempire.4delphi.com/delphi/ -
Lockfree approach on a Single reader, Multiple Writer queue
Primož Gabrijelčič replied to kokoslolos's topic in Algorithms, Data Structures and Class Design
As I said before, don't "believe" that the writer works ok - run tests! -
Lockfree approach on a Single reader, Multiple Writer queue
Primož Gabrijelčič replied to kokoslolos's topic in Algorithms, Data Structures and Class Design
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? -
Lockfree approach on a Single reader, Multiple Writer queue
Primož Gabrijelčič replied to kokoslolos's topic in Algorithms, Data Structures and Class Design
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! -
Lockfree approach on a Single reader, Multiple Writer queue
Primož Gabrijelčič replied to kokoslolos's topic in Algorithms, Data Structures and Class Design
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. -
GExperts Grep can use the MAP file
Primož Gabrijelčič replied to dummzeuch's topic in Tips / Blogs / Tutorials / Videos
Good one, thank you! -
Communication between processes (IPC)
Primož Gabrijelčič replied to Dzirt's topic in OmniThreadLibrary
@Jacek Laskowski, thank you for the correction. I will try to remember that in the future 🙂 -
Communication between processes (IPC)
Primož Gabrijelčič replied to Dzirt's topic in OmniThreadLibrary
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