Some flags for CreateThread

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Some flags for CreateThread

Post by PB »

I've got a problem where when I create a thread, it starts running immediately,
which I suspect is the normal behaviour? But even if I pause it immediately,
I still sometimes get an error because the thread has started before the
PauseThread command has kicked in. So maybe CreateThread could have
another flag to tell it pause the thread when created? Here's some code
which demonstrates my problem:

Code: Select all

Global th

Procedure MyThread()
  Repeat
    Debug "Thread"
    PauseThread(th)
  ForEver
EndProcedure

th=CreateThread(@MyThread(),0)
If th=0 : End : Else : PauseThread(th) : EndIf

Debug "Main loop"
Repeat : Sleep_(1) : ForEver
If you run this, 9 times out of 10 you'll see "Main loop" in the Debug Output,
which is great. But occasionally, you'll see "Thread" there first, because
the thread has started before PauseThread in the If/EndIf check is done.
This causes my app to crash, because the thread is trying to do something
when my Main Loop isn't ready yet... even though I've paused the thread
immediately after creating it. :(

So, I was thinking, maybe we could have an optional flag to pause the
thread as soon as it's created, to prevent this happening? Perhaps like:

Code: Select all

th=CreateThread(@MyThread(),0,#PB_Thread_Paused)
And while I think of it, maybe another flag to set the priority of the thread
too? Like: #PB_Thread_Low, #PB_Thread_BelowNormal, #PB_Thread_Normal,
#PB_Thread_AboveNormal, #PB_Thread_High, #PB_Thread_RealTime?

So to create a new thread that's paused upon creation with a high priority:

Code: Select all

th=CreateThread(@MyThread(),0,#PB_Thread_Paused|#PB_Thread_High)
Too much? :) I think it'd be very handy.

EDIT: Okay, I know I can easily just do it like this...

Code: Select all

Procedure MyThread()
  Repeat
    PauseThread(th)
    Debug "Thread"
  ForEver
EndProcedure
...but there may be situations where pausing it like that won't do (I can't
think of any), so if it's easy enough to put in, yeah, go for it. :) Or at least
put in the priority flags? :D
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
dmoc
Enthusiast
Enthusiast
Posts: 739
Joined: Sat Apr 26, 2003 12:40 am

Post by dmoc »

Mutex at start of thead (aka semaphore)?

Edit: Just a thought: tried Pausethread() within the thread? Sounds dodgy to me also :P (oh, I see u have)
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

@dmoc: :)

I just noticed the CreateThread Win32 API call actually supports a flag called
CREATE_SUSPENDED, which, as you can guess, does exactly what I want:

If the CREATE_SUSPENDED flag is specified, the thread is created in a
suspended state, and will not run until the ResumeThread function is
called. If this value is zero, the thread runs immediately after creation.


So it should be trivial to add this to PureBasic's version? :)
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

:?:

Code: Select all

Procedure MyThread(pause.l) 
  If pause ; these three lines can be used
    PauseThread(GetCurrentThread_()) ; in any thread, you don't
  EndIf ; need global variables
  Debug "thread"
EndProcedure 

th=CreateThread(@MyThread(),1) ; Use 1 for pause, 0 for not pause
If th=0
  End
EndIf 

Debug "Main loop" 
Delay(10)
dmoc
Enthusiast
Enthusiast
Posts: 739
Joined: Sat Apr 26, 2003 12:40 am

Post by dmoc »

good info both - thanks
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

@Trond: Doesn't work; crashes on line 3 due to "the specified thread does not exist":

Image
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

PB wrote:@Trond: Doesn't work; crashes on line 3 due to "the specified thread does not exist":
The code I posted was for PB 4 beta 1. It seems Fred or Freak took a peek at this thread and decided to add some debugger checks...

You can:
- Run without debugger
- Do a trick with disable/enable debugger:

Code: Select all

...
    DisableDebugger
      PauseThread(GetCurrentThread_()) ; in any thread, you don't 
    EnableDebugger
...
- Replace PauseThread() with the API function SuspendThread_().
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

The Beta1 creates the same error message.

This can also be done through a mutex:

Code: Select all

Procedure thread(mutex)
  LockMutex(mutex)   ; this waits until the mutex is available
  UnlockMutex(mutex)
  FreeMutex(mutex)
  
  Debug "in thread"
EndProcedure

mutex = CreateMutex()
LockMutex(mutex)      ; lock the mutex before the thread starts

thread = CreateThread(@thread(), mutex)

Debug "main program"
MessageRequester("","waiting...")

UnlockMutex(mutex)  ; this causes the LockMutex() in the thread to return

WaitThread(thread)

End
quidquid Latine dictum sit altum videtur
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Post by Trond »

Ok, it seems like it was for 3.94.
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

> The code I posted was for PB 4 beta 1

Yeah... that's what I ran it on. :?: See my screenshot...

Anyway, it seems the easiest way to solve this would be to just support
the CREATE_SUSPENDED flag as per the CreateThread_() API command.
Then there's no need to muck around with things like disabling the debugger
or using mutexs or anything else like that. IMO. :)
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
freak
PureBasic Team
PureBasic Team
Posts: 5940
Joined: Fri Apr 25, 2003 5:21 pm
Location: Germany

Post by freak »

Well, as i see it this sort of thing is very rarely needed.
And Windows is the only OS supporting a native solution for this anyway. (we'd need to emulate it for the other OS)

So i think it makes more sense that if you really need to create a thread but
not run it (for what i can find no plausible reason actually), you just use a
solution like the mutex one above, which does the trick very well.
quidquid Latine dictum sit altum videtur
PB
PureBasic Expert
PureBasic Expert
Posts: 7581
Joined: Fri Apr 25, 2003 5:24 pm

Post by PB »

> Windows is the only OS supporting a native solution for this anyway.
> (we'd need to emulate it for the other OS)

That's fair enough... I will see if I can use the API call to create it instead
then; it's no big deal. Just thought it'd be easy to put in, but I can see now
it's more trouble than it's worth. Thanks for explaining.

> if you really need to create a thread but not run it (for what i can find
> no plausible reason actually)

What? There's many reasons for creating one but not running it immediately.
In my case, it's because it's for a background task that the user elects to
start at any time. You don't run such a thread immediately in such cases.
Therefore, it can't run until needed, but I must create it first because if the
creation fails, then there's no point running the app at all. Microsoft obviously
agrees with me as proven by the existence of CREATE_SUSPENDED. ;)
I compile using 5.31 (x86) on Win 7 Ultimate (64-bit).
"PureBasic won't be object oriented, period" - Fred.
dmoc
Enthusiast
Enthusiast
Posts: 739
Joined: Sat Apr 26, 2003 12:40 am

Post by dmoc »

Thread pooling?
Post Reply