Hi Alex,

I am struggling to understand picolisp IPC functions (hear, tell, rpc,
sync...).  I have attached code for the Dining Philosophers problem
which gets stuck after calling 'hear' in the philosopher (child)
process.  The idea is that each philosopher is a process which opens a
fifo and all philosophers talk to their neighbours via those fifos.

'hear' in the following snippet seems to block the whole process:

   ...
   (log 'before)
   (hear (mailbox I))
   (log 'after)
   ...

outputs

$ ~/picolisp/p phil.l
0 -1 0 before
1 -1 0 before
2 -1 0 before
3 -1 0 before
4 -1 0 before
: 

..only and does nothing afterwards.  I would expect 'hear' to install
some kind of event handler which would evaluate incoming messages and
then carry on immediately with the next (log 'after) line.  Is my
understanding correct?  I though that 'hear' was working in the
background so why the code blocks?

Thank you,

Tomas

# ~/picolisp/p phil.l
# http://en.wikipedia.org/wiki/Dining_philosophers_problem
# Chandy / Misra solution
# philosophers: N = total, I = current, P = other
# forks: L = left, R = right; lt0 ~ dirty, =0 none, gt0 ~ clean

(de log @
   (pass println I L R)
   (flush) )

(de idle ()
   (wait (rand 1000 3000)) )

(de left ()
   (% (+ N (- I 1)) N) )
   
(de right ()
   (% (+ I 1) N) )

(de mailbox (P)
   (pack "phil" P) )

(de obtain (P)
   (log 'obtain P)
   (when (= P (left))
      (if (=0 L)
         (setq L 1)
         (quit "Already have the left fork") ) )
   (when (= P (right))
      (if (=0 R)
         (setq R 1)
         (quit "Already have the right fork") ) ) )

(de give (P)
   (log 'give P)
   (when (and (= P (left)) (lt0 L))
      (out (mailbox P)
         (rpc 'obtain I) )
      (setq L 0) )
   (when (and (= P (right)) (lt0 R))
      (out (mailbox P)
         (rpc 'obtain I) )
      (setq R 0) ) )
   
(de grab ()
   (while (or (=0 L) (=0 R))
      (when (lt0 L)
         (setq L 1) )
      (when (lt0 R)
         (setq R 1) )
      (when (=0 L)
         (out (mailbox (left))
            (rpc 'give I) ) )
      (when (=0 R)
         (out (mailbox (right))
            (rpc 'give I) ) )
      (wait 500) ) )

(de phil (I N L R)
   (unless (info (mailbox I))
      (call 'mkfifo (mailbox I)) )
   (log 'before)
   (hear (mailbox I))
   (log 'after)
   (loop
      (log 'thinking)
      (idle) # think
      (log 'hungry)
      (grab)
      (log 'eating)
      (idle) # eat
      (setq L -1 R -1) ) ) # dirty

(de main (N)
   (push '*Bye '(mapc 'kill *C))
   (for (I 0 (< I N) (inc I))
      (if (fork)
         (push '*C @)
         (phil I N -1 0) ) ) )

(main 5)

Reply via email to