fork()

Share your advanced PureBasic knowledge/code with the community.
PolyVector
Enthusiast
Enthusiast
Posts: 499
Joined: Wed Sep 17, 2003 9:17 pm
Location: Southern California
Contact:

fork()

Post by PolyVector »

Code updated For 5.20+

I was just playing around with the idea of creating a fork() function and I came up with this:...

Code: Select all

Global _ForkRet.l
EnableASM
Procedure _fork(RetAddy.l)
  MOV eax,#True
  CALL RetAddy
  ProcedureReturn #False
EndProcedure
Procedure fork()
  !MOV eax,[esp+20]
  !MOV [v__ForkRet],eax
  CreateThread(@_fork(),_ForkRet)
  ProcedureReturn #False
EndProcedure


;/Example:

If fork()
  Debug "FORKED"
  MessageRequester("Fork()","Forked :)")
  !RET
EndIf

MessageRequester("","We're Done...")
Tell me if it works... I'm not so sure with this [esp+20] thing but if PB doesn't change too much i'm sure it'll be fine... It works on 3.91 at least :)
Last edited by PolyVector on Sun Jan 09, 2005 8:13 pm, edited 4 times in total.
GPI
PureBasic Expert
PureBasic Expert
Posts: 1394
Joined: Fri Apr 25, 2003 6:41 pm

Post by GPI »

What do this function?
PolyVector
Enthusiast
Enthusiast
Posts: 499
Joined: Wed Sep 17, 2003 9:17 pm
Location: Southern California
Contact:

Post by PolyVector »

it forks the running process into two...
the code that executes when fork() is true is in a newly created thread (it is executed asyncronously...)
you MUST "!RET" to kill the newly created thread!

This should be built into PB....Fred? :)
Last edited by PolyVector on Sun Jan 09, 2005 8:27 pm, edited 2 times in total.
Bonne_den_kule
Addict
Addict
Posts: 841
Joined: Mon Jun 07, 2004 7:10 pm

Post by Bonne_den_kule »

What is this good for? what can it do?
PolyVector
Enthusiast
Enthusiast
Posts: 499
Joined: Wed Sep 17, 2003 9:17 pm
Location: Southern California
Contact:

Post by PolyVector »

it's a simple way of creating a thread...
if there's a function that blocks input you can simply call it within an "if fork()" and it will no longer block input... this is pretty standard on linux... read up on it :)

I'll try to think of a better example...
venom
User
User
Posts: 56
Joined: Fri Jul 25, 2003 1:54 pm
Location: Australia

Post by venom »

In what cases would it return false?
PolyVector
Enthusiast
Enthusiast
Posts: 499
Joined: Wed Sep 17, 2003 9:17 pm
Location: Southern California
Contact:

Post by PolyVector »

Here's a break-down of how it works...

1) It creates a new thread... Let's call this "Thread B" (The original is "Thread A")
2) Inside of Thread B it returns #True
3) Inside of Thread A it returns #False

Thread B must "!RET" when it's finished to destroy the new thread...

The simple way to think of it is this....

Code: Select all

If fork()
  ;/We're in a new thread...
  !RET
EndIf
;/Continue as usual...

It could very easily be modified to return the ThreadID to "Thread A" and #False to "Thread B"... this would be more like the real version of fork()... but I figured this syntax would be easier to understand for beginners...
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

What is the value you think you are getting with: !MOV eax,[esp+20] ??
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
Pupil
Enthusiast
Enthusiast
Posts: 715
Joined: Fri Apr 25, 2003 3:56 pm

Post by Pupil »

Psychophanta wrote:What is the value you think you are getting with: !MOV eax,[esp+20] ??
I think it's the return address from where the procedure was called.
PolyVector
Enthusiast
Enthusiast
Posts: 499
Joined: Wed Sep 17, 2003 9:17 pm
Location: Southern California
Contact:

Post by PolyVector »

yup, it's the return address... I asked about this in a thread a few months ago... PB pushes a few registers onto the stack so it's further up than usual...

If pb ever changes it's behavior, then "!MOV eax,[esp+20]" will have to have a different offset...
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

PolyVector wrote:yup, it's the return address... I asked about this in a thread a few months ago... PB pushes a few registers onto the stack so it's further up than usual...

If pb ever changes it's behavior, then "!MOV eax,[esp+20]" will have to have a different offset...
I see.
Sorry, i didn't see the other thread months ago 8)
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
PolyVector
Enthusiast
Enthusiast
Posts: 499
Joined: Wed Sep 17, 2003 9:17 pm
Location: Southern California
Contact:

Post by PolyVector »

you have been forgiven :D

Try this out... (I'm not sure why this amuses me)

Code: Select all

If fork() Or fork() Or fork()
  Debug "FORKED"
  MessageRequester("Fork()","Forked :)")
  !RET
EndIf

MessageRequester("","We're Done...")
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

Look at this:

Code: Select all

Global _ForkRet.l 
Procedure _fork(RetAddy.l) 
  !MOV eax,1 
  !CALL dword[esp] 
  ProcedureReturn 0 
EndProcedure 
Procedure fork() 
  !MOV eax,[esp+20] 
  !MOV [v__ForkRet],eax 
  CreateThread(@_fork(),_ForkRet) 
  ProcedureReturn 0
EndProcedure 

;/Example: 

If fork() 
  Debug "FORKED" 
  !RET 
Else
  Debug "NOT FORKED" 
EndIf 
In fact, the condition is False, but the True routine is executed by the CALL asm command in _fork() function (the secondary threat).
So then, the main thread is the stuff after the "Else" command, and the secondary thread is the one after the "If" command.
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

PolyVector wrote:Try this out... (I'm not sure why this amuses me)

Code: Select all

If fork() Or fork() Or fork()
  Debug "FORKED"
  MessageRequester("Fork()","Forked :)")
  !RET
EndIf

MessageRequester("","We're Done...")
Yes, the first call to fork() (in the "If" line) returns as #False, but is is executed, which means that all stuff after the "If" line is made (coz the CALL command inside _fork() function). Then, since there are an "Or" statement, the 2nd fork() call is executed too, which means the all stuff after "If" statement is made too. Then the 3rd. fork() call is made too (with a return result o #False too), and once again, the stuff is executed.
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
User avatar
Psychophanta
Always Here
Always Here
Posts: 5153
Joined: Wed Jun 11, 2003 9:33 pm
Location: Anare
Contact:

Post by Psychophanta »

PolyVector, could be this a final version?

Code: Select all

Global _ForkRet.l
Procedure _fork(RetAddy.l)
  !CALL dword[esp]
EndProcedure
Procedure fork()
  !MOV eax,dword[esp+20]
  !MOV dword[v__ForkRet],eax
  CreateThread(@_fork(),_ForkRet)
  ProcedureReturn 0
EndProcedure

;/Example:

If fork()
;Put here the 2ndary thread code:
  Debug "FORKED"
;End of 2ndary thread code
  !RET
Else
;and here de 1ary thread code:
  Debug "NOT FORKED"
;End of 1ary thread code.
EndIf
http://www.zeitgeistmovie.com

while (world==business) world+=mafia;
Post Reply