Hi Tomas, independent of the discussed problems with 'hear', I would actually not use 'hear' for this purpose.
If you look in the reference for 'hear', it says "hear is usually only called explicitly by a top level parent process". The reason is that upon a 'fork', the 'hear' channel is automatically set up in the child process to be used by the built-in IPC routines. As a consequence, if you re-open that channel with 'hear', the child is effectively cut off from its parent and could, for example, not synchronize on DB operations. So the recommended and natural way is to use 'tell'. In combination with 'pid', it can also send messages selectively to other processes. This solution has the additional advantage that no external fifos are required. As an example, I modified your "phil.l" (I hope I understood it). Each philosopher (process) keeps the PIDs of his neighbors in the global variables '*LeftNeighbor' and '*RightNeighbor', and the state of the forks in '*LeftFork' and '*RightFork'. In the beginning, he waits until he received the PIDs from the parent process. Cheers, - Alex
# ~/picolisp/p phil.l # http://en.wikipedia.org/wiki/Dining_philosophers_problem # Chandy / Misra solution # *Philosophers List of PIDs (process IDs) # *LeftNeighbor PID of left neighbor # *RightNeighbor PID of right neighbor # *LeftFork Left fork (NIL, dirty or clean) # *RightFork Right fork (NIL, dirty or clean) (de log @ (pass println *Pid *LeftFork *RightFork) (flush) ) (de idle () (wait (rand 1000 3000)) ) (de obtain (P) (log 'obtain P) (cond ((= P *LeftNeighbor) (if *LeftFork (quit "Already have the left fork") (setq *LeftFork 'clean) ) ) ((= P *RightNeighbor) (if *RightFork (quit "Already have the right fork") (setq *RightFork 'clean) ) ) ) ) (de give (P) (log 'give P) (cond ((= P *LeftNeighbor) (when (== 'dirty *LeftFork) (tell 'pid P 'obtain *Pid) (off *LeftFork) ) ) ((= P *RightNeighbor) (when (== 'dirty *RightFork) (tell 'pid P 'obtain *Pid) (off *RightFork) ) ) ) ) (de grab () (until (and *LeftFork *RightFork) (cond ((== 'dirty *LeftFork) (setq *LeftFork 'clean) ) ((not *LeftFork) (tell 'pid *LeftNeighbor 'give *Pid) ) ) (cond ((== 'dirty *RightFork) (setq *RightFork 'clean) ) ((not *RightFork) (tell 'pid *RightNeighbor 'give *Pid) ) ) (wait 500) ) ) (de phil () (wait NIL (and *LeftNeighbor *RightNeighbor)) (setq *LeftFork 'dirty) (loop (log 'thinking) (idle) # think (log 'hungry) (grab) (log 'eating) (idle) # eat (setq *LeftFork (setq *RightFork 'dirty)) ) ) (de main (N) (setq *Philosophers # Build a list of PIDs (make (do N (if (fork) (link @) (phil)) ) ) ) (push '*Bye '(mapc kill *Philosophers)) (do N # Send to each philosopher the PIDs of his neighbors (tell 'pid (car *Philosophers) 'setq '*LeftNeighbor (last *Philosophers) '*RightNeighbor (cadr *Philosophers) ) (rot *Philosophers) ) ) (main 5)