Skip to content

Commit cc188a2

Browse files
authored
Merge pull request #771 from devlights/add-future-promise-example
2 parents 49d5b72 + 530594f commit cc188a2

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# https://taskfile.dev
2+
3+
version: '3'
4+
5+
tasks:
6+
default:
7+
cmds:
8+
- go run main.go
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"sync"
6+
"time"
7+
)
8+
9+
type (
10+
// Future[T] は、「今はまだ得られていないが将来得られるはずの入力」を表します。
11+
Future[T any] struct {
12+
value T
13+
wait chan struct{}
14+
}
15+
16+
// Promise[T] は、「将来値を提供するという約束」を表します。
17+
Promise[T any] struct {
18+
f *Future[T]
19+
}
20+
)
21+
22+
func (me *Future[T]) IsDone() bool {
23+
select {
24+
case <-me.wait:
25+
return true
26+
default:
27+
return false
28+
}
29+
}
30+
31+
func (me *Future[T]) set(v T) {
32+
if me.IsDone() {
33+
return
34+
}
35+
36+
me.value = v
37+
close(me.wait)
38+
}
39+
40+
func (me *Future[T]) Get() T {
41+
<-me.wait
42+
return me.value
43+
}
44+
45+
func (me *Promise[T]) Submit(v T) {
46+
me.f.set(v)
47+
}
48+
49+
func NewPromise[T any]() (*Future[T], *Promise[T]) {
50+
f := &Future[T]{wait: make(chan struct{})}
51+
p := &Promise[T]{f: f}
52+
53+
return f, p
54+
}
55+
56+
func init() {
57+
log.SetFlags(log.Ltime)
58+
}
59+
60+
func main() {
61+
log.Println("START")
62+
defer log.Println("END ")
63+
64+
var (
65+
f1, p1 = NewPromise[int]()
66+
f2, p2 = NewPromise[string]()
67+
wg sync.WaitGroup
68+
)
69+
70+
wg.Add(3)
71+
72+
// f1に依存する処理
73+
//
74+
// f2の状態に関係なく、f1が完了したら完了する
75+
go func(f *Future[int]) {
76+
defer wg.Done()
77+
log.Printf("f1=%v", f1.Get())
78+
}(f1)
79+
80+
// f2に依存する処理
81+
//
82+
// f1の状態に関係なく、f2が完了したら完了する
83+
go func(f *Future[string]) {
84+
defer wg.Done()
85+
log.Printf("f2=%v", f2.Get())
86+
}(f2)
87+
88+
// f1とf2に依存する処理
89+
//
90+
// f1, f2の2つのFutureが完了しないと処理が完了しない
91+
go func(f1 *Future[int], f2 *Future[string]) {
92+
defer wg.Done()
93+
log.Printf("f1=%v\tf2=%v", f1.Get(), f2.Get())
94+
}(f1, f2)
95+
96+
// 1秒後にf1に値を提供する
97+
//
98+
// このPromiseが値を提供するまで対応するFuture(f1)は結果を返さない
99+
go func(p *Promise[int]) {
100+
time.Sleep(1 * time.Second)
101+
p.Submit(999)
102+
}(p1)
103+
104+
// 3秒後にf2に値を提供する
105+
//
106+
// このPromiseが値を提供するまで対応するFuture(f2)は結果を返さない
107+
go func(p *Promise[string]) {
108+
time.Sleep(3 * time.Second)
109+
p.Submit("hello world")
110+
}(p2)
111+
112+
wg.Wait()
113+
114+
/*
115+
$ task -d examples/singleapp/future_promise/
116+
task: [default] go run main.go
117+
08:19:13 START
118+
08:19:14 f1=999
119+
08:19:16 f2=hello world
120+
08:19:16 f1=999 f2=hello world
121+
08:19:16 END
122+
*/
123+
124+
}

0 commit comments

Comments
 (0)