Using a thread to (partially) manage the server state

This commit is contained in:
Tony Garnock-Jones 2012-07-17 12:07:17 -04:00
parent c3a95afecf
commit 68c75d381a
1 changed files with 60 additions and 0 deletions

60
chat-threadstate.rkt Normal file
View File

@ -0,0 +1,60 @@
#lang racket/base
(require racket/set)
(require racket/match)
(require racket/tcp)
(require racket/port)
(define (main)
(define listener (tcp-listen 5999 4 #t))
(let loop ()
(define-values (cin cout) (tcp-accept listener))
(define-values (local-host local-port remote-host remote-port) (tcp-addresses cin #t))
(thread (connection-handler cin cout (cons remote-host remote-port)))
(loop)))
(define (connection-handler cin cout connection-id)
(lambda ()
(with-handlers ((exn:fail? (lambda (e)
(thread-send active-connection-thread
`(depart ,(current-thread) ,connection-id))
(raise e))))
(thread-send active-connection-thread `(arrive ,(current-thread) ,connection-id))
(let loop ()
(sync (wrap-evt (read-bytes-line-evt cin 'any)
(lambda (line)
(cond [(eof-object? line) 'done]
[else
(for ([c active-connections])
(thread-send (car c) `(says ,connection-id ,line)))
(loop)])))
(wrap-evt (thread-receive-evt)
(lambda (dummy)
(write (thread-receive) cout)
(newline cout)
(flush-output cout)
(loop)))))
(thread-send active-connection-thread `(depart ,(current-thread) ,connection-id)))))
(define active-connections (set))
(define active-connection-thread
(thread
(lambda ()
(let loop ()
(match (thread-receive)
[`(arrive ,caller ,connection-id)
(thread-send caller `(you-are ,connection-id))
(for ([c active-connections])
(thread-send caller `(arrived ,(cdr c)))
(thread-send (car c) `(arrived ,connection-id)))
(define new-connections (set-add active-connections (cons caller connection-id)))
(set! active-connections new-connections)]
[`(depart ,caller ,connection-id)
(define new-connections (set-remove active-connections (cons caller connection-id)))
(set! active-connections new-connections)
(for ([c active-connections]) (thread-send (car c) `(departed ,connection-id)))])
(loop)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(main)