Recent

Author Topic: Simple multithreading code example in Free Pascal  (Read 21365 times)

semichaud1

  • New Member
  • *
  • Posts: 38
Re: Simple multithreading code example in Free Pascal
« Reply #15 on: April 18, 2018, 02:52:38 am »
Thanks cdbc!

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Simple multithreading code example in Free Pascal
« Reply #16 on: April 18, 2018, 02:58:09 am »
So from what I can figure the shaking graphics (only characters are shaking, the background tiles are not) comes from the fact that the main thread is rendering the characters while the additional thread is still processing the characters coordinates when they move.
Not entirely. The shaking comes from the fact that things are not in sync (or simply take too much time).

Quote
So I have no choice but to include the procedure in the main thread instead.
No, yo still can use threads (and when implemented properly they are able to speed up your engine). However, most games are linear to such extend that using threads makes absolutely no sense at all.

On the other hand (and as a hopefully simple example) imagine that you have need for a longwinded movement calculation for an endboss that you know is upcoming if the player continues onward, then you could calculate some things in advance while the player hasn't reached this endboss yet, and loads it's graphics from disk.

Quote
I will find some other use for the additional thread, for example  quicksaves without interrupting gameplay. I was thinking I could also use an additional thread for the calculations relating to combat in the game. Then have the main thread render the combat graphics separately but I will have to only process variables that have no impact on the graphics at all. Like how much hp a target loses and what status effects are applied but that so low in computational demands that I'm starting to wonder why have multithreading at all except for quicksaves. Sound effects maybe.
Threads requires syncing and that doesn't play very well with linear advancement of a 2d game that needs direct visualization in order to react (speedy) on game-events.

I really wonder what it is that takes so much time to calculate because that is usually not a problem unless you already have a bottleneck somewhere in there. Mind that a mistake/oversight can be made very easily in game-development. have you timed your calculation and are perhaps able to provide us an average time that is taken by your calculations ?

PS: why do people keep advertising 3th party thread libraries. SDL has it's own threading support and none of the 3th party thread libraries will actually solve TS' problem instead just waste TS' time.

semichaud1

  • New Member
  • *
  • Posts: 38
Re: Simple multithreading code example in Free Pascal
« Reply #17 on: April 18, 2018, 03:45:27 am »
Thanks for all the advice molly.

What I am running in a separate thread is only the procedure for updating character position based on input from the player. Also my game is a party-based rpg so I have three other characters following the controlled character around. In that procedure is also the code for updating the other characters' position so they follow the controlled character. I am not using an A star pathfinding algorithm for that. I simply made my own algorithm based on what I observed playing Chrono Trigger :) (I have programmed A star in the past and I plan to do it again for this project). So the algorithm is very light. Now that I think about it part of that algorithm is situated in a procedure in the main loop as well. It could be that also causing the problem. Because the only graphics shaking are the sprites for the characters. The background and object tiles layers are not shaking. Unforunately, I cannot decouple that code from the procedure in the main loop. The character follow algorithm would not run properly and there is no other structure that would make it run properly, according to logic. I'll have a look again later today. It's 2:45 am and I have to start work in a bit.
« Last Edit: April 18, 2018, 03:48:20 am by semichaud1 »

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Simple multithreading code example in Free Pascal
« Reply #18 on: April 18, 2018, 04:49:09 am »
No problem semichaud1. Please take your time.

If i got you to think about your implementation and this made you come up with a possible culprit (and indeed that sounds like one) then the goal was reached  :)

Your 'follow' algorithm could be an example that could be situated inside a thread. As long as the path doesn't change during (at least some) frame updates then you could pre-calc that path for a certain amount of frames and use that inside your main thread to graphically update your character's sprite positions (in a timely/synced) manner of course. Every time you main character changes direction you can start that thread again and repeat the process (or do a thread for every individual sprite, although that seems counterproductive for a-search paths) . If it is actually worth the effort in that you will gain speed in your overall performance is questionable though, especially when calculations are 'light'.

Epand

  • New Member
  • *
  • Posts: 25
Re: Simple multithreading code example in Free Pascal
« Reply #19 on: February 11, 2022, 12:02:10 pm »
As simple as it can be but not simpler:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}
  2.  
  3. uses
  4.   {$ifdef unix}
  5.   cthreads,
  6.   {$endif}
  7.   Classes;
  8.  
  9. type
  10.   TMyThread = class(TThread)
  11.     procedure Execute; override;
  12.   end;
  13.  
  14. procedure TMyThread.Execute;
  15. begin
  16.   WriteLn('I am thread with ID ',ThreadID);
  17. end;
  18.  
  19. var
  20.   t1,t2,t3: TThread;
  21. begin
  22.   // create all threads in suspended state
  23.   t1 := TMyThread.Create(true); t1.FreeOnTerminate := true;
  24.   t2 := TMyThread.Create(true); t2.FreeOnTerminate := true;
  25.   t3 := TMyThread.Create(true); t3.FreeOnTerminate := true;
  26.  
  27.   t1.Start; t2.Start; t3.Start; // start them all
  28.   t1.WaitFor; t2.WaitFor; t3.WaitFor; // wait for them all to finish before exiting main thread
  29. end.
  30.  

Although these postings are almost 4 years old, I would like to ask something regarding "As simple as it can be".
Keeping in mind the quoted example and keeping it very simple further on, what is the most simple way
(A) for the main thread to signal one of the multi threads without waiting for response
and
(B) for the multi threads to signal among each other?

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Simple multithreading code example in Free Pascal
« Reply #20 on: February 11, 2022, 12:15:22 pm »
The easiest way to do this is to create a thread safe message queue for that thread which is checked regularly.
You can use TQueue from Generics.Collections for the queue and make it thread safe by using Critical Sections: https://www.freepascal.org/docs-html/prog/progse45.html

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Simple multithreading code example in Free Pascal
« Reply #21 on: February 11, 2022, 12:15:33 pm »
Read the manual? Comes with multiple very simple examples:
https://www.freepascal.org/docs-html/rtl/classes/tthread.executeinthread.html

The examples are at the bottom. Easier than that is hard to do...
Specialize a type, not a var.

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Simple multithreading code example in Free Pascal
« Reply #22 on: February 11, 2022, 12:17:43 pm »
The easiest way to do this is to create a thread safe message queue for that thread which is checked regularly.
You can use TQueue from Generics.Collections for the queue and make it thread safe by using Critical Sections: https://www.freepascal.org/docs-html/prog/progse45.html
Or simply a https://www.freepascal.org/docs-html/rtl/classes/tthreadlist.html again, manual...
Just like my previous post. (Generics are great, but not even close to necessary here.)
« Last Edit: February 11, 2022, 12:19:56 pm by Thaddy »
Specialize a type, not a var.

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Simple multithreading code example in Free Pascal
« Reply #23 on: February 11, 2022, 12:26:04 pm »
I don't see that much of a difference writing
Code: Pascal  [Select][+][-]
  1. lst := ThreadedList.Lock;
  2. try
  3.   Item := lst[0];
  4.   lst.Delete(0);
  5. finally
  6.   ThreadedList.Unlock;
  7. end;
versus:
Code: Pascal  [Select][+][-]
  1. EnterCriticalSection(QueueSection);
  2. try
  3.   Item := MessageQueue.Dequeue;
  4. finally
  5.   LeaveCriticalSection(QueueSection);
  6. end;

I think that when you want to implement a queue, you should use a queue type, and not a list type simulating a queue. Because using a queue type makes clear how it is used, and also thereby enforces the intendet usage. (Not to mention that queue types are probably optimised to be a Queue)

Also note that generics.Collections also has a generic version of TThreadList

The easiest way to do this is to create a thread safe message queue for that thread which is checked regularly.
You can use TQueue from Generics.Collections for the queue and make it thread safe by using Critical Sections: https://www.freepascal.org/docs-html/prog/progse45.html
This creates a new thread, it does not send a message to an existing worker thread as asked
« Last Edit: February 11, 2022, 12:42:31 pm by Warfley »

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Simple multithreading code example in Free Pascal
« Reply #24 on: February 11, 2022, 12:50:33 pm »
TThreadedList? It is TThreadList...
Specialize a type, not a var.

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Simple multithreading code example in Free Pascal
« Reply #25 on: February 11, 2022, 12:53:49 pm »
TThreadedList? It is TThreadList...
Yep, have made a typo, but it was already corrected before you posted this
« Last Edit: February 11, 2022, 12:56:47 pm by Warfley »

avk

  • Hero Member
  • *****
  • Posts: 752
Re: Simple multithreading code example in Free Pascal
« Reply #26 on: February 11, 2022, 01:01:41 pm »
I don't see that much of a difference writing
Code: Pascal  [Select][+][-]
  1. lst := ThreadedList.Lock;
  2. try
  3.   Item := lst[0];
  4.   lst.Delete(0);
  5. finally
  6.   ThreadedList.Unlock;
  7. end;
versus:
Code: Pascal  [Select][+][-]
  1. EnterCriticalSection(QueueSection);
  2. try
  3.   Item := MessageQueue.Dequeue;
  4. finally
  5.   LeaveCriticalSection(QueueSection);
  6. end;
...

And meanwhile, there is a difference, and it is noticeable: the first one has a quadratic complexity of element extraction.
However, the second also has its own problems.

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: Simple multithreading code example in Free Pascal
« Reply #27 on: February 11, 2022, 01:09:18 pm »
And meanwhile, there is a difference, and it is noticeable: the first one has a quadratic complexity of element extraction.
However, the second also has its own problems.
Thats true, but I think it is fair to assume that message queues will probably stay rather small, so complexity isn't going to be much of an issue here. That said, when the queue is running on a high throughput and capacity, this can seriously be a problem. But in most cases I think the overhead from the critical sections dominates anyway (when the thread just has to go to sleep once, this is probably more overhead than a few thousand list accesses).
« Last Edit: February 11, 2022, 01:10:59 pm by Warfley »

Thaddy

  • Hero Member
  • *****
  • Posts: 14205
  • Probably until I exterminate Putin.
Re: Simple multithreading code example in Free Pascal
« Reply #28 on: February 11, 2022, 01:09:28 pm »
In my opinion this can be solved with InterlockedExchangePtr.
But hey, let's stick to the subject: simple!
Specialize a type, not a var.

Epand

  • New Member
  • *
  • Posts: 25
Re: Simple multithreading code example in Free Pascal
« Reply #29 on: February 11, 2022, 03:05:19 pm »

The easiest way to do this is to create a...

Comes with multiple very simple examples...

Sorry that I did not see the wood for the trees.
Thanks for the hints.

 

TinyPortal © 2005-2018