October 20, 2021, 11:31:51

Author Topic: [SOLVED] CreateThread() within Types?  (Read 267 times)

Offline Midimaster

  • Sr. Member
  • ****
  • Posts: 363
    • Midimaster Music Education Software
[SOLVED] CreateThread() within Types?
« on: July 15, 2021, 06:12:44 »
For my Ringbuffer I need a Thread which controls the feeding of the audio-device independent of the users main code. So the user needs to add a function WatchLoop() and register it with CreateThread():
Code: BlitzMax
  1. Global RingBuffer:RingBufferClass = New RingBufferClass
  2. Local WatchThread:TThread=CreateThread(WatchLoop, "")
  3. ....
  4.  
  5. Function  WatchLoop:Object(data:Object)
  6.         Repeat
  7.                 Delay 3
  8.                 RingBuffer.Watch
  9.         Forever
  10. End Function
  11.  
  12.  
  13. Type RingBufferClass
  14.          .....
  15.          Method Watch()
  16.                 ....
  17.         End Method
  18. End Type
  19.  

This runs perfect. The code of the function WatchLoop() is fix and needs not to be changed by the user.


As the code is always the same I would like to make the function WatchLoop() a part of the TYPE RingBufferClass.
But when I try this:
Code: BlitzMax
  1. Global RingBuffer:RingBufferClass = New RingBufferClass
  2. Local WatchThread:TThread=CreateThread(RingBuffer.WatchLoop_B, "")
  3. ....
  4.  
  5. Type RingBufferClass
  6.         .....
  7.         Method Watch()
  8.                 ....
  9.         End Method
  10.  
  11.         Method WatchLoop_B:Object(data:Object)
  12.                 Repeat
  13.                         Delay 3
  14.                         Watch
  15.                 Forever
  16.         End Method
  17. End Type
  18.  

...I get this error message:
Code: [Select]
Compile Error: Missing function argument 'data'.
[C:/BasicNG/FreeAudio/rauschen.bmx;15;0]
Build Error: failed to compile (-1) C:/BasicNG/FreeAudio/rauschen.bmx

What do I forget?

How can I integrate Thread-functions as a Method of a TYPE?

« Last Edit: July 15, 2021, 08:22:02 by Midimaster »
See my current project on PlayStore: 20Tracks-Audio-Player https://play.google.com/store/apps/details?id=midimaster.twentytrackd

Offline Derron

  • Hero Member
  • *****
  • Posts: 3667
Re: CreateThread() within Types?
« Reply #1 on: July 15, 2021, 07:13:27 »
You already identified that you tried to pass a "method" instead of a "function".

You need to pass a function to "CreateThread" but you can also pass "data" (which you pass empty for now - as "").
A Method is a function with the instance passed as "first parameter" so like a "function(self, firstparameter)" instead of "self.method(firstparameter)".

So ... your current approach would be to create a new thread for each ringbuffer ... ok that's then:

Code: BlitzMax
  1. Global RingBuffer:RingBufferClass = New RingBufferClass
  2. Local WatchThread:TThread=CreateThread(RingBufferClass.WatchLoop, RingBuffer)
  3. ....
  4.  
  5. Type RingBufferClass
  6.         .....
  7.         Method Watch()
  8.                 ....
  9.         End Method
  10.  
  11.         Function WatchLoop:Object(data:Object)
  12.                 Local buffer:RingBufferClass = RingBufferClass(data)
  13.                 If not buffer then Return Null  
  14.                 Repeat
  15.                         Delay 3
  16.                         buffer.Watch()
  17.                 Forever
  18.         End Function
  19. End Type
  20.  

So you pass the "to use buffer" as param to the createThread-call. And inside the function you cast that back into your class.


the issue is: you would create a new thread for each buffer you create. You could also have a thread which "watch()" all known buffers (so store all buffers in a "active" collection and iterate over this list/array ...

Btw you could create this thread as soon as you actually want to use you. So instead of precreating the thread you could have some "Init()" method in the buffer class which creates a thread if not done yet.
Or even have some Methods - which check an integer if true or false, and if not initialized yet, create the thread.


bye
Ron

Offline Midimaster

  • Sr. Member
  • ****
  • Posts: 363
    • Midimaster Music Education Software
Re: CreateThread() within Types?
« Reply #2 on: July 15, 2021, 08:16:28 »
...So you pass the "to use buffer" as param to the createThread-call. And inside the function you cast that back into your class...

Ron, you are the best! I completely understand your explanation. Thanks a lot for the detailed description. I never understood, what this "data:Object" is good for.

I immediately added this to my RingBufferClass. Now it looks more professional and it is more comfortable for the user, because he need not to think about registering the thread:
 
Code: BlitzMax
  1. Global RingBuffer:RingBufferClass = New RingBufferClass
  2. RingBuffer.CreateNew(12000, SF_MONO16LE)
  3. 'thats all!
  4. ...
  5. Type RingBufferClass
  6.         Method CreateNew(Hertz:Int, UserFormat:Int=SF_STEREO16LE , Latency:Int=8)
  7.                 ...
  8.                 Local WatchThread:TThread = CreateThread(WatchLoop,Self)
  9.         End Method
  10.  
  11. Private
  12.  
  13.         Method Watch()
  14.                 ...
  15.         End Method
  16.  
  17.         Function WatchLoop:Object(data:Object)
  18.                 Local RingBuffer:RingBufferClass = RingBufferClass(data)
  19.                 If Not RingBuffer Then Return Null  
  20.                 Repeat
  21.                         Delay 3
  22.                         RingBuffer.Watch
  23.                 Forever
  24.         End Function
  25. End Type
  26.  

As you can see I also changed the point, where the thread is created. This was my original objective. With your help I could reach it.

Only three questions remaining:

1.
Can the variable WatchThread:TThread stay local? Or need I store it into a field of the instance?

2.
Does this casting of data has any consequences on performance?

3.
Do I need to unregister those threads. Or does END of the main code stopp also the threads correctly?
 
See my current project on PlayStore: 20Tracks-Audio-Player https://play.google.com/store/apps/details?id=midimaster.twentytrackd

Offline Henri

  • Sr. Member
  • ****
  • Posts: 355
Re: [SOLVED] CreateThread() within Types?
« Reply #3 on: July 15, 2021, 08:34:24 »
Methods and local variables reside in the stack memory that is erased after use, so for this reason you can't use them in any instance where a handling function is required (aka callback function like in Createthread). Functions and globals reside in heap memory that is constant for the whole lifespan of the application.

1. thread will have a life of its own regardless, but if you want to check if the thread is running or terminate it, you need to store the id somewhere.

2. No.

3. You do not need to unregister threads. They will remove themselves after they done or are manually terminated or when the application closes.

-Henri
- Got 01100011 problems, but the bit ain't 00000001

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal