@@ -10,6 +10,7 @@ import (
1010// Find what's wrong in the exercise() function
1111// Make sure all the tests are passing
1212// DO NOT remove any Sleep() calls
13+ // DO NOT remove any steps, i.e: transfer, check, revert
1314
1415// try running this with the -race flag
1516// go run -race exercise.go
@@ -18,24 +19,34 @@ import (
1819// GOFLAGS="-count=1" go test .
1920
2021func main () {
21- exercise ()
22+ now := time .Now ()
23+ accounts := exercise ()
24+ for _ , a := range accounts {
25+ fmt .Printf ("'%s' amount: $%v\n " , a .id , a .amount )
26+ fmt .Printf ("'%s' transactions: %v\n " , a .id , a .transactions )
27+ }
28+ fmt .Println ("elapsed:" , time .Since (now ))
2229}
2330
24- func exercise () {
31+ func exercise () [] * account {
2532 var mu sync.Mutex
26- var n1 , n2 int
27- f1 , f2 := file {mu : & mu , name : "f1" }, file {mu : & mu , name : "f2" }
28- //write := func(f *file, name1, name2 string) {
29- // for i := 0; i < 5; i++ {
30- // if f.write([]byte(name1)) || f.write([]byte(name2)) {
31- // return
32- // }
33- // }
34- //}
35- write := func (f * file , n1 , n2 * int ) {
33+ accounts := []* account {
34+ {id : "a1" , amount : 5 },
35+ {id : "a2" , amount : 10 },
36+ }
37+ b1 := bank {mu : & mu , name : "bank1" }
38+ b2 := bank {mu : & mu , name : "bank2" }
39+ write := func (b * bank , amount float64 , accounts ... * account ) {
3640 for i := 0 ; i < 5 ; i ++ {
37- if f .write (n1 ) || f .write (n2 ) {
38- fmt .Println (f .name , "successfully wrote to file" )
41+ ok := true
42+ for _ , a := range accounts {
43+ if ! b .transfer (a , amount ) {
44+ ok = false
45+ break
46+ }
47+ }
48+ if ok {
49+ fmt .Printf ("'%s' successfully transferred: $%v\n " , b .name , amount )
3950 return
4051 }
4152 }
@@ -45,48 +56,55 @@ func exercise() {
4556 wg .Add (2 )
4657 go func () {
4758 defer wg .Done ()
48- write (& f1 , & n1 , & n2 )
59+ // transfer $200 from bank1 to all accounts
60+ write (& b1 , 200 , accounts ... )
4961 }()
5062 go func () {
5163 defer wg .Done ()
52- write (& f2 , & n1 , & n2 )
64+ // transfer $100 from bank2 to all accounts
65+ write (& b2 , 100 , accounts ... )
5366 }()
5467
5568 wg .Wait ()
56- fmt .Println (n1 )
57- fmt .Println (n2 )
69+ return accounts
5870}
5971
60- type file struct {
72+ type account struct {
73+ id string
74+ amount float64
75+ transactions []string
76+ }
77+
78+ type bank struct {
6179 name string
6280 mu * sync.Mutex
63- //data []byte
6481}
6582
66- //func (f *file) write(data []byte) bool {
67- func (f * file ) write (n * int ) bool {
68- fmt .Println (f .name , "trying to write" , * n )
69- f .mu .Lock ()
70- //f.data = data
71- * n += 1
72- f .mu .Unlock ()
83+ func (b * bank ) transfer (acc * account , amount float64 ) bool {
84+ // transfer the money
85+ fmt .Printf ("'%s' trying to transfer: $%v to '%s'\n " , b .name , amount , acc .id )
86+ b .mu .Lock ()
87+ acc .amount += amount
88+ b .mu .Unlock ()
7389 time .Sleep (500 * time .Millisecond )
7490
75- f .mu .Lock ()
76- //if bytes.Equal(f.data, data) {
77- if * n == 1 {
78- f .mu .Unlock ()
91+ // check if the money were transferred
92+ b .mu .Lock ()
93+ // if current balance equals to previous account balance
94+ if acc .amount == acc .amount - amount {
95+ b .mu .Unlock ()
96+ tx := fmt .Sprintf ("%s: $%v" , b .name , amount )
97+ acc .transactions = append (acc .transactions , tx )
7998 return true
8099 }
81- f .mu .Unlock ()
82-
100+ b .mu .Unlock ()
83101
84102 time .Sleep (100 * time .Millisecond )
85103
86- f . mu . Lock ()
87- //f.data = nil
88- * n -= 1
89- f .mu .Unlock ()
104+ // revert the transfer
105+ b . mu . Lock ()
106+ acc . amount -= amount
107+ b .mu .Unlock ()
90108 time .Sleep (500 * time .Millisecond )
91109 return false
92110}
0 commit comments