arc> (def fork ()
(ccc
(fn (c)
(thread (c nil)))))
arc> (if (fork)
(prn "parent")
(prn "child"))
parent
"parent"
arc> continuation application: attempted to cross a continuation barrier
Am I missing something here, or is it simply not possible to call a continuation from inside another thread?If I can't call a continuation inside another thread, is there a way to call fork() from inside mzscheme? (I've heard that 'subprocess calls fork(), but I don't know if that is really what I want or not, and I can't find any documentation on it.)
Any other suggestions as to how I could simulate fork would be appreciated.
If you're looking to exec a new process, subprocess will do that; it's documented at http://download.plt-scheme.org/doc/mzscheme/mzscheme-Z-H-15....
You asked about doing a wait; you pass the child's pid to wait.
Returning to your original example, Mzscheme supports calling continuations from another thread, as documented at http://download.plt-scheme.org/doc/mzscheme/mzscheme-Z-H-6.h... That page also describes the continuation barriers. The issue is that you can't have a new thread call a continuation in the main thread, since then you'd have two main REPL threads, which doesn't make sense.
What you need to do is run your example in yet another thread:
arc> (def doit () (if (fork) (prn "Parent") (prn "Child")))
arc> (thread (doit))
Then you'll get the result you're expecting.-----
Is there a way to wait for a thread to end, other than something like
(let th (thread (sleep 1))
(until (dead th))
(pr 'done))
Also, is there a way to make a thread-local variable so threads don't all try to update the same global variable? For example (= pid 0)
(def test ()
(let parent? (fork)
(= pid (+ (* pid 2) (if parent? 0 1)))))
(thread
(test)
(test)
(test)
(prn pid))
prints 0, 1, 12, 25, 102, 205, 822, 1645, which much larger than the expected 1, 2, 3, 4, 5, 6, 7, 8 because all the threads update the same global variable-----
(= foo (thread-local))
(foo) ; read the variable
(= (foo) 42) ; write the variable
Also, I've added semaphores to Anarki. If you want to wait on another thread: (let s (sema)
; thread you're waiting on
(thread
(sleep 1)
(sema-post s))
; monitoring thread
(sync s)
(pr 'done))
As mentioned, Anarki only ^^-----
(w/uniq void
(mac w/thread-local (var (o val void))
(if (is val void)
`(= ,var (thread-local))
`(do (= ,var (thread-local))
(= (,var) ,val)))))
then you could do (w/thread-local foo 0)
instead of the two step initialization (= foo (thread-local))
(= (foo) 0)-----
And if you have to know, I am trying to port a program entered in the 5th annual Obfuscated Perl Contest (http://perl.plover.com/obfuscated/). It was originally implemented using fork(), but I was experimenting with using continuations and threads just to see if it would work.
-----
-----
I do have one question about loading libc. Since the system doesn't automatically find libc.so for you, you need to name the path explicitly. What worked for me was
(w/ffi "/lib/libc.so.6"
(cdef fork "fork" cint ()))
but I don't really know if this is the right way to do it. Is there a better way?-----
A better alternative with mzscheme's foreign interface is to use `#f' for the library -- that treats the mzscheme binary as the library to open (which includes the usual libc stuff.)
-----
It does not know the size of malloced objects however, so be careful (no pb there, but if you allocate something very big, mzscheme will only see a new reference and will not necessarily call GC when you will actually lack memory).
-----