Browse code

pkg/package: remove promise package

The promise package represents a simple enough concurrency pattern that
replicating it in place is sufficient. To end the propagation of this
package, it has been removed and the uses have been inlined.

While this code could likely be refactored to be simpler without the
package, the changes have been minimized to reduce the possibility of
defects. Someone else may want to do further refactoring to remove
closures and reduce the number of goroutines in use.

Signed-off-by: Stephen J Day <stephen.day@docker.com>

Stephen J Day authored on 2017/09/22 09:56:45
Showing 5 changed files
... ...
@@ -7,7 +7,6 @@ import (
7 7
 	"golang.org/x/net/context"
8 8
 
9 9
 	"github.com/docker/docker/pkg/pools"
10
-	"github.com/docker/docker/pkg/promise"
11 10
 	"github.com/docker/docker/pkg/term"
12 11
 	"github.com/sirupsen/logrus"
13 12
 )
... ...
@@ -58,7 +57,7 @@ func (c *Config) AttachStreams(cfg *AttachConfig) {
58 58
 }
59 59
 
60 60
 // CopyStreams starts goroutines to copy data in and out to/from the container
61
-func (c *Config) CopyStreams(ctx context.Context, cfg *AttachConfig) chan error {
61
+func (c *Config) CopyStreams(ctx context.Context, cfg *AttachConfig) <-chan error {
62 62
 	var (
63 63
 		wg     sync.WaitGroup
64 64
 		errors = make(chan error, 3)
... ...
@@ -137,35 +136,42 @@ func (c *Config) CopyStreams(ctx context.Context, cfg *AttachConfig) chan error
137 137
 	go attachStream("stdout", cfg.Stdout, cfg.CStdout)
138 138
 	go attachStream("stderr", cfg.Stderr, cfg.CStderr)
139 139
 
140
-	return promise.Go(func() error {
141
-		done := make(chan struct{})
142
-		go func() {
143
-			wg.Wait()
144
-			close(done)
145
-		}()
146
-		select {
147
-		case <-done:
148
-		case <-ctx.Done():
149
-			// close all pipes
150
-			if cfg.CStdin != nil {
151
-				cfg.CStdin.Close()
152
-			}
153
-			if cfg.CStdout != nil {
154
-				cfg.CStdout.Close()
155
-			}
156
-			if cfg.CStderr != nil {
157
-				cfg.CStderr.Close()
140
+	errs := make(chan error, 1)
141
+
142
+	go func() {
143
+		defer close(errs)
144
+		errs <- func() error {
145
+			done := make(chan struct{})
146
+			go func() {
147
+				wg.Wait()
148
+				close(done)
149
+			}()
150
+			select {
151
+			case <-done:
152
+			case <-ctx.Done():
153
+				// close all pipes
154
+				if cfg.CStdin != nil {
155
+					cfg.CStdin.Close()
156
+				}
157
+				if cfg.CStdout != nil {
158
+					cfg.CStdout.Close()
159
+				}
160
+				if cfg.CStderr != nil {
161
+					cfg.CStderr.Close()
162
+				}
163
+				<-done
158 164
 			}
159
-			<-done
160
-		}
161
-		close(errors)
162
-		for err := range errors {
163
-			if err != nil {
164
-				return err
165
+			close(errors)
166
+			for err := range errors {
167
+				if err != nil {
168
+					return err
169
+				}
165 170
 			}
166
-		}
167
-		return nil
168
-	})
171
+			return nil
172
+		}()
173
+	}()
174
+
175
+	return errs
169 176
 }
170 177
 
171 178
 func copyEscapable(dst io.Writer, src io.ReadCloser, keys []byte) (written int64, err error) {
... ...
@@ -20,7 +20,6 @@ import (
20 20
 	"github.com/docker/docker/pkg/idtools"
21 21
 	"github.com/docker/docker/pkg/ioutils"
22 22
 	"github.com/docker/docker/pkg/pools"
23
-	"github.com/docker/docker/pkg/promise"
24 23
 	"github.com/docker/docker/pkg/system"
25 24
 	"github.com/sirupsen/logrus"
26 25
 )
... ...
@@ -1095,36 +1094,42 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
1095 1095
 	}
1096 1096
 
1097 1097
 	r, w := io.Pipe()
1098
-	errC := promise.Go(func() error {
1099
-		defer w.Close()
1098
+	errC := make(chan error, 1)
1100 1099
 
1101
-		srcF, err := os.Open(src)
1102
-		if err != nil {
1103
-			return err
1104
-		}
1105
-		defer srcF.Close()
1100
+	go func() {
1101
+		defer close(errC)
1106 1102
 
1107
-		hdr, err := tar.FileInfoHeader(srcSt, "")
1108
-		if err != nil {
1109
-			return err
1110
-		}
1111
-		hdr.Name = filepath.Base(dst)
1112
-		hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
1103
+		errC <- func() error {
1104
+			defer w.Close()
1113 1105
 
1114
-		if err := remapIDs(archiver.IDMappingsVar, hdr); err != nil {
1115
-			return err
1116
-		}
1106
+			srcF, err := os.Open(src)
1107
+			if err != nil {
1108
+				return err
1109
+			}
1110
+			defer srcF.Close()
1117 1111
 
1118
-		tw := tar.NewWriter(w)
1119
-		defer tw.Close()
1120
-		if err := tw.WriteHeader(hdr); err != nil {
1121
-			return err
1122
-		}
1123
-		if _, err := io.Copy(tw, srcF); err != nil {
1124
-			return err
1125
-		}
1126
-		return nil
1127
-	})
1112
+			hdr, err := tar.FileInfoHeader(srcSt, "")
1113
+			if err != nil {
1114
+				return err
1115
+			}
1116
+			hdr.Name = filepath.Base(dst)
1117
+			hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
1118
+
1119
+			if err := remapIDs(archiver.IDMappingsVar, hdr); err != nil {
1120
+				return err
1121
+			}
1122
+
1123
+			tw := tar.NewWriter(w)
1124
+			defer tw.Close()
1125
+			if err := tw.WriteHeader(hdr); err != nil {
1126
+				return err
1127
+			}
1128
+			if _, err := io.Copy(tw, srcF); err != nil {
1129
+				return err
1130
+			}
1131
+			return nil
1132
+		}()
1133
+	}()
1128 1134
 	defer func() {
1129 1135
 		if er := <-errC; err == nil && er != nil {
1130 1136
 			err = er
... ...
@@ -9,7 +9,6 @@ import (
9 9
 
10 10
 	"github.com/docker/docker/pkg/archive"
11 11
 	"github.com/docker/docker/pkg/idtools"
12
-	"github.com/docker/docker/pkg/promise"
13 12
 	"github.com/docker/docker/pkg/system"
14 13
 	"github.com/sirupsen/logrus"
15 14
 )
... ...
@@ -122,40 +121,45 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
122 122
 	}
123 123
 
124 124
 	r, w := io.Pipe()
125
-	errC := promise.Go(func() error {
126
-		defer w.Close()
127
-
128
-		srcF, err := srcDriver.Open(src)
129
-		if err != nil {
130
-			return err
131
-		}
132
-		defer srcF.Close()
133
-
134
-		hdr, err := tar.FileInfoHeader(srcSt, "")
135
-		if err != nil {
136
-			return err
137
-		}
138
-		hdr.Name = dstDriver.Base(dst)
139
-		if dstDriver.OS() == "windows" {
140
-			hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
141
-		} else {
142
-			hdr.Mode = int64(os.FileMode(hdr.Mode))
143
-		}
144
-
145
-		if err := remapIDs(archiver.IDMappingsVar, hdr); err != nil {
146
-			return err
147
-		}
148
-
149
-		tw := tar.NewWriter(w)
150
-		defer tw.Close()
151
-		if err := tw.WriteHeader(hdr); err != nil {
152
-			return err
153
-		}
154
-		if _, err := io.Copy(tw, srcF); err != nil {
155
-			return err
156
-		}
157
-		return nil
158
-	})
125
+	errC := make(chan error, 1)
126
+
127
+	go func() {
128
+		defer close(errC)
129
+		errC <- func() error {
130
+			defer w.Close()
131
+
132
+			srcF, err := srcDriver.Open(src)
133
+			if err != nil {
134
+				return err
135
+			}
136
+			defer srcF.Close()
137
+
138
+			hdr, err := tar.FileInfoHeader(srcSt, "")
139
+			if err != nil {
140
+				return err
141
+			}
142
+			hdr.Name = dstDriver.Base(dst)
143
+			if dstDriver.OS() == "windows" {
144
+				hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
145
+			} else {
146
+				hdr.Mode = int64(os.FileMode(hdr.Mode))
147
+			}
148
+
149
+			if err := remapIDs(archiver.IDMappingsVar, hdr); err != nil {
150
+				return err
151
+			}
152
+
153
+			tw := tar.NewWriter(w)
154
+			defer tw.Close()
155
+			if err := tw.WriteHeader(hdr); err != nil {
156
+				return err
157
+			}
158
+			if _, err := io.Copy(tw, srcF); err != nil {
159
+				return err
160
+			}
161
+			return nil
162
+		}()
163
+	}()
159 164
 	defer func() {
160 165
 		if er := <-errC; err == nil && er != nil {
161 166
 			err = er
162 167
deleted file mode 100644
... ...
@@ -1,11 +0,0 @@
1
-package promise
2
-
3
-// Go is a basic promise implementation: it wraps calls a function in a goroutine,
4
-// and returns a channel which will later return the function's return value.
5
-func Go(f func() error) chan error {
6
-	ch := make(chan error, 1)
7
-	go func() {
8
-		ch <- f()
9
-	}()
10
-	return ch
11
-}
12 1
deleted file mode 100644
... ...
@@ -1,25 +0,0 @@
1
-package promise
2
-
3
-import (
4
-	"errors"
5
-	"testing"
6
-
7
-	"github.com/stretchr/testify/require"
8
-)
9
-
10
-func TestGo(t *testing.T) {
11
-	errCh := Go(functionWithError)
12
-	er := <-errCh
13
-	require.EqualValues(t, "Error Occurred", er.Error())
14
-
15
-	noErrCh := Go(functionWithNoError)
16
-	er = <-noErrCh
17
-	require.Nil(t, er)
18
-}
19
-
20
-func functionWithError() (err error) {
21
-	return errors.New("Error Occurred")
22
-}
23
-func functionWithNoError() (err error) {
24
-	return nil
25
-}