Skip to content

Commit 5c839e9

Browse files
committed
Add implementation of exercise 3-47
1 parent c0a1915 commit 5c839e9

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed

README.org

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
习题完成情况:
2626
- 章节一: 43/46
2727
- 章节二: 88/97
28-
- 章节三: 46/82
28+
- 章节三: 47/82
2929
- 章节四: TODO
3030
- 章节五: TODO
3131
* 运行

chapter3/exercise3-47.rkt

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#lang racket
2+
3+
(require "mutex.rkt")
4+
5+
(define (make-semaphore n)
6+
(let ((count n)
7+
(mutex (make-mutex)))
8+
(define (acquire)
9+
(let loop ()
10+
(mutex 'acquire)
11+
(if (> count 0)
12+
(begin
13+
(set! count (- count 1))
14+
(mutex 'release))
15+
(begin
16+
(mutex 'release)
17+
(sleep 0.01)
18+
(loop)))))
19+
20+
(define (release)
21+
(mutex 'acquire)
22+
(set (count (+ count 1)))
23+
(mutex 'release))
24+
25+
(lambda (m)
26+
(cond ((eq? m 'acquire) acquire)
27+
((eq? m 'release) release)
28+
(else (error "Unknown operation " m))))))
29+
30+
(module+ test
31+
(require rackunit)
32+
33+
(test-case "Basic semaphore operations"
34+
(define sem (make-semaphore 2))
35+
36+
(check-not-exn (lambda () (sem 'acquire)))
37+
(check-not-exn (lambda () (sem 'acquire)))
38+
39+
(check-not-exn (lambda () (sem 'release))))
40+
41+
(test-case "Threading test"
42+
(define sem (make-semaphore 1))
43+
(define results '())
44+
(define result-mutex (make-mutex))
45+
46+
(define (add-result x)
47+
(result-mutex 'acquire)
48+
(set! results (cons x results))
49+
(result-mutex 'release))
50+
51+
(sem 'acquire)
52+
53+
(thread (lambda ()
54+
(sleep 0.05)
55+
(add-result 'thread-started)
56+
(sem 'acquire)
57+
(add-result 'thread-acquired)
58+
(sem 'release)))
59+
60+
(add-result 'main-holding)
61+
(add-result 'main-releasing)
62+
(sem 'release)
63+
64+
;; Give thread time to complete
65+
(sleep 0.2)
66+
(check-equal? (car results) 'thread-acquired)
67+
(check-equal? (car (cdr results)) 'thread-started)
68+
)
69+
)

chapter3/mutex.rkt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#lang racket
2+
(define (test-and-set! cell)
3+
;; box-cas! is atomic operation
4+
(not (box-cas! cell #f #t)))
5+
6+
(define (make-mutex)
7+
(let ((cell (box #f)))
8+
(define (the-mutex m)
9+
(cond ((eq? m 'acquire)
10+
(when (test-and-set! cell)
11+
;; retry
12+
(the-mutex 'acquire)))
13+
((eq? m 'release)
14+
(clear! cell))))
15+
the-mutex))
16+
17+
(define (clear! cell)
18+
(box-cas! cell #t #f))
19+
20+
(provide make-mutex)

0 commit comments

Comments
 (0)