Arc Forumnew | comments | leaders | submitlogin
4 points by kens 6094 days ago | link | parent

I'll step back and ask what you're trying to do with fork. If you do a genuine fork, you'll end up with two mzscheme interpreters running, which may or may not be what you want.

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.


1 point by eds 6092 days ago | link

Now I have two questions about threads:

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

-----

2 points by almkglor 6092 days ago | link

I recently added thread-local variables to Anarki (last week or week before last, maybe). To use:

  (= 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 ^^

-----

2 points by eds 6092 days ago | link

Looking at 'sync documentation, it would seem that you can also just call 'sync on a thread to wait for it to end.

  (let th
    ; thread you're waiting on
    (thread
      (sleep 1))
    ; monitoring thread
    (sync th)
    (pr 'done))

-----

1 point by eds 6092 days ago | link

Thanks, that is exactly what I wanted. Although it might be nice to have a macro wrapper around 'thread-local for initializing variables

  (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)

-----

1 point by eds 6092 days ago | link

Thanks for the information on continuations and threads. Your suggestion worked perfectly for me.

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.

-----

2 points by kens 6092 days ago | link

I took a look at the Perl program. Just a warning: Arc doesn't have real pipes, so if you try to synchronize on pipes like the Arc program, you're in for trouble. Also, if you implement real forks and fork 32 mzscheme interpreters in parallel, you better have a bigger computer than mine :-)

-----

2 points by almkglor 6092 days ago | link

I also added pipes to Anarki.

  (let (input-end output-end) (pipe)
    (...do what you will...))

-----