For those who like making threaded programs but...

Share your advanced PureBasic knowledge/code with the community.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

For those who like making threaded programs but...

Post by dracflamloc »

Code updated For 5.20+

This little tidbit of code can be used to operate similar to threads without the risk and overhead of being thread-safe. Good for 3.94 and doing games and dx interaction as well. Easily converted to pb4...

Code: Select all

    Structure TASK_INFO
      function.l
      lastTimeMs.l
      delayMs.l
      autoremove.b
      parameter.l
      useParam.b
    EndStructure

    Global NewList TaskList.TASK_INFO()

    Procedure RegisterTask(*func,delay.l,autoremove.b)
      AddElement(TaskList())
      TaskList()\function=*func
      TaskList()\delayms=delay
      TaskList()\lastTimeMs=ElapsedMilliseconds()-1
      TaskList()\autoremove=autoremove
    EndProcedure

    Procedure RegisterTaskEx(*func,delay.l,autoremove.b,parameter.l)
      AddElement(TaskList())
      TaskList()\function=*func
      TaskList()\delayms=delay
      TaskList()\lastTimeMs=ElapsedMilliseconds()-1
      TaskList()\parameter=parameter
      TaskList()\useparam=1
      TaskList()\autoremove=autoremove
    EndProcedure

    Procedure RunTasks(nowMs.l)
      ForEach TaskList()
        If nowMs - TaskList()\lastTimeMs >= TaskList()\delayMs
          If TaskList()\UseParam
            CallFunctionFast(TaskList()\function,TaskList()\parameter)
          Else
            CallFunctionFast(TaskList()\function)
          EndIf
          TaskList()\lastTimeMs=nowMs
        EndIf
      Next
     
      ForEach TaskList()
        If TaskList()\autoremove And TaskList()\lastTimeMs=nowMs
          DeleteElement(TaskList())
        EndIf
      Next
    EndProcedure

Just do: RunTasks(ElapsedMilliseconds()) in your main loop.
Last edited by dracflamloc on Tue Jun 20, 2006 12:43 pm, edited 1 time in total.
srod
PureBasic Expert
PureBasic Expert
Posts: 10589
Joined: Wed Oct 29, 2003 4:35 pm
Location: Beyond the pale...

Post by srod »

Hey, that's pretty cool! 8) Nice idea.

Thanks.
I may look like a mule, but I'm not a complete ass.
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

Thanks for sharing, it's a well-thought and well-written piece of code!

Ok, now the downside: The main strength of a thread is that it executes asyncronously, that is it'll do its thing without holding up execution of the main program. For me that's most of why I'd use a thread, and unfortunately the main loop in this approach is going to wait patiently until the CallFunctionFast() has returned before moving on with its desperately-vital tasks, all of which are most certainly crucial to the survival of the planet. (ok maybe not, but they do want to continue while the thread runs)
Last edited by netmaestro on Tue Jun 20, 2006 7:26 am, edited 1 time in total.
BERESHEIT
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Post by Rescator »

Actually, tasks aren't truly "async" either.
We are getting closer to that though with dual core or multi cpu setups.
Bonne_den_kule
Addict
Addict
Posts: 841
Joined: Mon Jun 07, 2004 7:10 pm

Post by Bonne_den_kule »

Nice idea.
dioxin
User
User
Posts: 97
Joined: Thu May 11, 2006 9:53 pm

Post by dioxin »

I'm with Netmaestro on the downside.

Threads are completely different to what you have here.
Your code is treated as a single process by the OS and is given a single timeslice at any time in which to run. All of your "threads" will share that one timeslice.
Real threads are each given their own independant timeslice by the OS and the OS will determine which thread runs and when.
e.g. If one thread accesses data from a file on disk the OS knows that this will take a while so it will immediately suspend that thread and the next thread will run while the disk drive fetches the data. In your case, the CPU will wait until the data is got from the disk, and no other task will run while your function fetches data so the CPU time is lost and the overall program runs more slowly.

without the risk and overhead of being thread-safe
There is no risk to being thread safe and you only need the overhead when its useful, i.e. you choose when to make things thread safe to suit the application.

Paul.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

can be used to operate similar to threads
I never said they were the same. But they can acheive a similar effect while still allowing thread-like coding. This is because modern CPUs are so fast a smaller task should execute so quickly it appears to be executing like a thread would. Also realize that this actually can be *more* accurate than using a thread loop with a Delay() because Delay() only guarentees that the thread will wait at LEAST that long, so if you delay(10) it might wait 13 or 20 or 30 until the next available time it can get to run.

Use it or don't? :roll:

(Oh and thanks Rescator :wink:)

I was gonna say that but you covered it.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

Btw I changed the code a bit. (ElapsedMilliseconds-1)
dioxin
User
User
Posts: 97
Joined: Thu May 11, 2006 9:53 pm

Post by dioxin »

Rescator,
Actually, tasks aren't truly "async" either.
Threads are.
Asynchronous doesn't mean simultaneous. The threads don't run at the exact same time but they do run without regard to the timing of other threads unless you deliberately keep them in sync.
We are getting closer to that though with dual core or multi cpu setups.
The technique shown here will not benefit from multiple CPUs as it still remains a single process and will be tied to a single CPU.
Threads are each created with their own process and can each run on a different CPU if one is available.

Paul.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

I don't think thats what he meant...

But anyway the whole point of this code was for people who make games in PB and cant use multithreading because of DX and other things. Debate this somewhere else.
dioxin
User
User
Posts: 97
Joined: Thu May 11, 2006 9:53 pm

Post by dioxin »

Debate this somewhere else.
That would make no sense.

Paul.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

It makes damn perfect sense. If you want to use this code and have recommendations for changes and features then say so here in this thread. Debating threading and multi-cpu machines does not belong in my tips and tricks thread.
dioxin
User
User
Posts: 97
Joined: Thu May 11, 2006 9:53 pm

Post by dioxin »

dracflamloc,
your initial post, first line says:
This little tidbit of code can be used to operate similar to threads without the risk and overhead of being thread-safe.
Points which distinguish your approach from true threads are therefore valid since you draw comparisons between your approach and threads. It's perfectly reasonable to also point out the differences.

You imply that threaded code is risky which it isn't (not unless PB has a problem with it that I don't know about).

It would be misleading to not post a discussion here as anyone with less knowledge of the subject could mistakenly come across your code, believe that it performs in a similar way to threaded code and believe that threaded code is risky and may never look into real threads and completely miss out on the advantages that real threaded code gives.

Since the main purpose of this place is to help others I see nothing wrong with helping others reading this to understand the difference between your approach and threaded code. To not do so would be unprofessional.

Debating threading and multi-cpu machines does not belong..
Explaining how your approach differs from threaded code does belong here as you initially draw the comparison yourself.
Multi CPU comments were directed at Rescator who appeared to confusing asynchronous with multi/single CPUs.

Paul.
dracflamloc
Addict
Addict
Posts: 1648
Joined: Mon Sep 20, 2004 3:52 pm
Contact:

Post by dracflamloc »

Using threads with strings, linkedlists, sprite libraries, as well as pb's networking commands can cause problems and crashes. I stated the reasons for using this code. I just said it can be used similar to threads. You dont like it thats fine.

And of course, you are the utmost in professionalism. :?
User avatar
netmaestro
PureBasic Bullfrog
PureBasic Bullfrog
Posts: 8451
Joined: Wed Jul 06, 2005 5:42 am
Location: Fort Nelson, BC, Canada

Post by netmaestro »

@dracflamloc, I like your code and I'm going to use it. I just took a second to point out that it'll still execute non-async and I had no idea it would start anything. Sorry!
BERESHEIT
Post Reply