1
2
3
4
5 package main
6
7 import (
8 "context"
9 "io"
10 "os"
11 "runtime"
12 "runtime/pprof"
13 "sync"
14 )
15
16 func init() {
17 register("Etcd5509", Etcd5509)
18 }
19
20 var ErrConnClosed_etcd5509 error
21
22 type Client_etcd5509 struct {
23 mu sync.RWMutex
24 ctx context.Context
25 cancel context.CancelFunc
26 }
27
28 func (c *Client_etcd5509) Close() {
29 c.mu.Lock()
30 defer c.mu.Unlock()
31 if c.cancel == nil {
32 return
33 }
34 c.cancel()
35 c.cancel = nil
36 c.mu.Unlock()
37 c.mu.Lock()
38 }
39
40 type remoteClient_etcd5509 struct {
41 client *Client_etcd5509
42 mu sync.Mutex
43 }
44
45 func (r *remoteClient_etcd5509) acquire(ctx context.Context) error {
46 for {
47 r.client.mu.RLock()
48 closed := r.client.cancel == nil
49 r.mu.Lock()
50 r.mu.Unlock()
51 if closed {
52 return ErrConnClosed_etcd5509
53 }
54 r.client.mu.RUnlock()
55 }
56 }
57
58 type kv_etcd5509 struct {
59 rc *remoteClient_etcd5509
60 }
61
62 func (kv *kv_etcd5509) Get(ctx context.Context) error {
63 return kv.Do(ctx)
64 }
65
66 func (kv *kv_etcd5509) Do(ctx context.Context) error {
67 for {
68 err := kv.do(ctx)
69 if err == nil {
70 return nil
71 }
72 return err
73 }
74 }
75
76 func (kv *kv_etcd5509) do(ctx context.Context) error {
77 err := kv.getRemote(ctx)
78 return err
79 }
80
81 func (kv *kv_etcd5509) getRemote(ctx context.Context) error {
82 return kv.rc.acquire(ctx)
83 }
84
85 type KV interface {
86 Get(ctx context.Context) error
87 Do(ctx context.Context) error
88 }
89
90 func NewKV_etcd5509(c *Client_etcd5509) KV {
91 return &kv_etcd5509{rc: &remoteClient_etcd5509{
92 client: c,
93 }}
94 }
95
96 func Etcd5509() {
97 prof := pprof.Lookup("goroutineleak")
98 defer func() {
99
100 for i := 0; i < yieldCount; i++ {
101 runtime.Gosched()
102 }
103 prof.WriteTo(os.Stdout, 2)
104 }()
105
106 go func() {
107 ctx, _ := context.WithCancel(context.TODO())
108 cli := &Client_etcd5509{
109 ctx: ctx,
110 }
111 kv := NewKV_etcd5509(cli)
112 donec := make(chan struct{})
113 go func() {
114 defer close(donec)
115 err := kv.Get(context.TODO())
116 if err != nil && err != ErrConnClosed_etcd5509 {
117 io.Discard.Write([]byte("Expect ErrConnClosed"))
118 }
119 }()
120
121 runtime.Gosched()
122 cli.Close()
123
124 <-donec
125 }()
126 }
127
View as plain text