;;;; -*- Scheme -*-
;;
;; bnawki example for HLSIM
;;
;; David DeRoure Sep 14 1997
;; dder@martigny.ai.mit.edu
;;
;; This file should be compiled with (cps "bnawki1") then 
;; (cbf "bnawki1").  It uses definitions in club5d.scm.  
;; See bnawki1s.scm for the simulation setup.  See the HLSIM 
;; documentation for further details.
;;
;; Each processor has a boolean state, which is initially chosen at 
;; random.  The processor repeatedly broadcasts its id and state, 
;; while also keeping count of its neighbors and their states.  The 
;; state of the processor is updated when the state of a neighbor 
;; changes, according to rules (which are in the definition file).  
;; The current state is represented by the color.  The period between 
;; broadcasts is random to reduce repeated collisions. 

(declare (usual-integrations))

;; Every processor has an id (not the processor number, as that would
;; be cheating)

(define processor-id (random 1000000))

;; Each processor has a boolean state, initially set by flipping a coin

(define state (zero? (random 2)))

;; Each processor maintains an association list of neigbors and their states.

(define neighbors (list))

;; If this is an isolated processor it will detect no communications
;; events and can go dormant after a period of time (neighbor-timeout).

(define no-messages-received? #T)

;; The transmit loop runs as long as transmit? is true.
;; It is set to false by the receive loop when this processor 
;; has finished its work.

(define transmit? #T)

(define collisions 0)

(define primitive-message-event (make-event))

(define (receive-loop)
  (select
    (global-timeout (set! transmit? #F))
    (primitive-message-event
     => (lambda (message)
          (event.clear! primitive-message-event)
	  (set! no-messages-received? #F)
          (if (eq? message 'collision)
	      (set! collisions (1+ collisions))
	      (begin (set! neighbors (update-table! neighbors message))
		     (set! state (next-state neighbors state))
		     (color-me (if state "white" "red"))))
	  (receive-loop)))
    (neighbor-timeout
     (event.clear! neighbor-timeout)
     (if no-messages-received?
	 (begin (color-me "black")
		(set! transmit? #F))))))

(define (transmit-loop)
  (wait (make-timeout-event (+ 100 (random 1000))))
  (broadcast (cons processor-id state))
  (if transmit? (transmit-loop)))
  
;; Run the loops

(define global-timeout (make-timeout-event 10000))
(define neighbor-timeout (make-timeout-event 5000))

(color-me "blue")

(parallel (transmit-loop) (receive-loop))

;; end of bnawki1.scm
