-
Content Count
246 -
Joined
-
Last visited
-
Days Won
11
Posts posted by Primož Gabrijelčič
-
-
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.
-
-
3 hours ago, M.Joos said:Yes, mine arrived yesterday.
Congrats! I'm still waiting on mine 😞
-
2 hours ago, Roberto Dall'Angelo said:Are there basic rules to understand the complexity? Like understand ifis O(n) or O(log n)
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.
-
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).
- 1
-
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.
-
50 minutes ago, David Millington said:We've seen the same error for other plugins too. So far we haven't tracked it down. Do you get a call stack?
No, just this message box.
-
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.
- 1
-
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.
-
10 minutes ago, Sherlock said:But is it still anonymous though?
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.
-
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.
- 1
- 1
-
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.
- 1
-
1 hour ago, Rudy Velthuis said:Obviously testing thread-related code is hard too.
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.
- 2
-
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.)
- 1
- 1
-
51 minutes ago, DiGi said:Just one complete offtopic "funny" web: https://deadlockempire.github.io/ - find deadlocks yourself...
There's a Delphi version, too: http://deadlockempire.4delphi.com/delphi/
- 2
- 2
-
As I said before, don't "believe" that the writer works ok - run tests!
-
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?
-
19 minutes ago, dummzeuch said:It explicitly says "single reader", so that's a non issue.
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!
-
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.
- 1
-
Good one, thank you!
-
-
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
- 1
-
23 hours ago, Andrea Magni said:you'll sign it one day 😉
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).
- 1
-
Original post: https://www.thedelphigeek.com/2019/02/design-patterns-with-delphi-book.html
Hurrah, hurray, my third book is here! It’s called Hands-On Design Patterns with Delphi and (just like my first book) I wrote it for Packt Publishing. (The second book was self-published and I expect the fourth one to be, too.)
As the name says, “Design Patterns with Delphi” deals with design patterns. It is a bit different from most of design pattern books and websites you will find on the Internet. Case in point A: There are no UML diagrams. I don‘t speak UML. Tried to learn it few times but for some reason the whole concept doesn‘t agree with me. If you like diagrams, don’t fear though. Any book on design patterns - and most websites covering that topic - will gladly show how any design pattern can be diagrammed. That, however, is not important and should not govern your decision to buy the book.
More important is case in point B: This book speaks Delphi. All the examples are written in Delphi and language features are used to the full. I also covered few less known Delphi idioms in separate sections. You’ll still be able to follow the discussion even though you may program in a different Pascal dialect.
There’s also case in point 😄 Examples make sense. I deeply dislike classical design pattern examples of the “And then we want to write this program for different toolkits and it should also be able to draw circles, not only squares” kind. Euch! I tried to find a good example for each design pattern. Admittedly, I ended with few examples that draw triangles and squares on screen (mostly because some patterns were designed specifically for solving such problems), but most of them are of a more practical nature.
This book covers all three classical design pattern categories - Creational patterns, Structural patterns, and Behavioral patterns. It also discusses patterns from the newer Concurrency patterns category. At the end I threw in some borderline-pattern(ish) topics and ended with a discussion of few patterns that cannot be strictly classified as “design” patterns.
In this book you’ll find:
-
Chapter 1
An introduction to patterns. Exploration of design principles, design patterns, and idioms. A mention of anti-patterns. A short description of most important design principles. Delphi idioms: creating and destroying objects. -
Chapter 2
Creation patterns part 1. Singleton. Dependency injection. Lazy initialization. Object pool. -
Chapter 3
Creation patterns part 2. Factory method, Abstract factory, Prototype, Builder. Delphi idioms: Assign and AssignTo. -
Chapter 4
Structural patterns part 1. Composite. Flyweight. Marker interface. Bridge. Delphi idioms: comparers and hashers. -
Chapter 5
Structure patterns part 2. Adapter. Proxy. Decorator. Facade. Delphi idioms: replacing components in runtime. Also: helpers. -
Chapter 6
Behavioral patterns part 1. Null object. Template method. Command. State. -
Chapter 7
Behavioral patterns part 2. Iterator. Visitor. Observer. Memento. Delphi idioms: for .. in. -
Chapter 8
Concurrency patterns part 1. Locking. Lock striping. Double-checked locking. Optimistic locking. Readers-writers lock. Delphi idioms: tasks and threads. Also: bitwise operators. -
Chapter 9
Concurrency patterns part 2. Thread pool. Messaging. Future. Pipeline. -
Chapter 10
Writing Delphi programs. Event-driven programming. Actions. LiveBindings. Form inheritance. Frames. Data modules. -
Chapter 11
Wrapping it up. Exceptions. Debugging. Functional programming.
I hope you will like this book and learn a lot from it. I know I did during the nine months I spent writing it. And if you find any bug in the code, let me know so I can correct it in the second release!
- 11
- 14
-
Chapter 1
Runtime Error on Closing with ScaleMM2 Memory Manager
in OmniThreadLibrary
Posted
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.