-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
xio: Add Reader/Writer/... interfaces - io analogs that add support f…
…or contexts In many cases IO needs to be able to be canceled. For example in WCFS filesystem I need to cancel handling sysread(/head/watch) when FUSE INTERRUPT request comes in [1,2,3]. The READ handler for /head/watch inside WCFS is interally implemented via io.Pipe which does not provide read/write cancellattion besides "destructive" close. Standard Go answer for cancellations is via contexts. So as a first step let's add corresponding interfaces - xio.Reader, xio.Writer etc - that are io analogs that add support for contexts. For compatibility with legacy code that work with only io.X (e.g. only with io.Reader), in spirit of [4], add BindCtx which binds xio.X instance with context and converts it into io.X. Add WithCtx - corresponding inverse operation that converts io.X back into xio.X and for general io.X adds cancellation handling on a best-effort basis. [1] https://lab.nexedi.com/kirr/wendelin.core/commit/b17aeb8c [2] https://lab.nexedi.com/kirr/wendelin.core/commit/f05271b1 [3] https://lab.nexedi.com/kirr/wendelin.core/commit/5ba816da [4] golang/go#20280 [5] golang/go#16522
- Loading branch information
Showing
2 changed files
with
372 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// Copyright (C) 2019 Nexedi SA and Contributors. | ||
// Kirill Smelkov <[email protected]> | ||
// | ||
// This program is free software: you can Use, Study, Modify and Redistribute | ||
// it under the terms of the GNU General Public License version 3, or (at your | ||
// option) any later version, as published by the Free Software Foundation. | ||
// | ||
// You can also Link and Combine this program with other software covered by | ||
// the terms of any of the Free Software licenses or any of the Open Source | ||
// Initiative approved licenses and Convey the resulting work. Corresponding | ||
// source of such a combination shall include the source code for all other | ||
// software used. | ||
// | ||
// This program is distributed WITHOUT ANY WARRANTY; without even the implied | ||
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
// | ||
// See COPYING file for full licensing terms. | ||
// See https://www.nexedi.com/licensing for rationale and options. | ||
|
||
package xio | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
) | ||
|
||
// xIO is test Reader/Writer/Closer/... | ||
type xIO struct{} | ||
|
||
func (_ *xIO) Read(ctx context.Context, dst []byte) (int, error) { | ||
for i := range dst { | ||
dst[i] = 0 | ||
} | ||
return len(dst), nil | ||
} | ||
|
||
func (_ *xIO) Write(ctx context.Context, src []byte) (int, error) { | ||
return len(src), nil | ||
} | ||
|
||
func (_ *xIO) Close() error { | ||
return nil | ||
} | ||
|
||
// tIO is test io.Reader/io.Writer/... | ||
type tIO struct{} | ||
|
||
func (_ *tIO) Read(dst []byte) (int, error) { | ||
for i := range dst { | ||
dst[i] = 0 | ||
} | ||
return len(dst), nil | ||
} | ||
|
||
func (_ *tIO) Write(src []byte) (int, error) { | ||
return len(src), nil | ||
} | ||
|
||
func (_ *tIO) Close() error { | ||
return nil | ||
} | ||
|
||
|
||
// ok1 asserts that v is true. | ||
func ok1(v bool) { | ||
if !v { | ||
panic("not ok") | ||
} | ||
} | ||
|
||
// Verify xio.X <-> io.X conversion | ||
func TestConvert(t *testing.T) { | ||
x := new(xIO) | ||
i := new(tIO) | ||
bg := context.Background() | ||
|
||
// WithCtx(BindCtx(X)) = X | ||
ok1( WithCtxR(BindCtxR(x, bg)) == x ) | ||
|
||
ok1( WithCtxW(BindCtxW(x, bg)) == x ) | ||
|
||
ok1( WithCtxR (BindCtxRW(x, bg)) == x ) | ||
ok1( WithCtxW (BindCtxRW(x, bg)) == x ) | ||
ok1( WithCtxRW(BindCtxRW(x, bg)) == x ) | ||
|
||
ok1( WithCtxR (BindCtxRC(x, bg)) == x ) | ||
ok1( WithCtxRC(BindCtxRC(x, bg)) == x ) | ||
|
||
ok1( WithCtxW (BindCtxWC(x, bg)) == x ) | ||
ok1( WithCtxWC(BindCtxWC(x, bg)) == x ) | ||
|
||
ok1( WithCtxR (BindCtxRWC(x, bg)) == x ) | ||
ok1( WithCtxW (BindCtxRWC(x, bg)) == x ) | ||
ok1( WithCtxRW (BindCtxRWC(x, bg)) == x ) | ||
ok1( WithCtxRC (BindCtxRWC(x, bg)) == x ) | ||
ok1( WithCtxWC (BindCtxRWC(x, bg)) == x ) | ||
ok1( WithCtxRWC(BindCtxRWC(x, bg)) == x ) | ||
|
||
|
||
// BindCtx(WithCtx(X), bg) = X | ||
ok1( BindCtxR(WithCtxR(i), bg) == i ) | ||
|
||
ok1( BindCtxW(WithCtxW(i), bg) == i ) | ||
|
||
ok1( BindCtxR (WithCtxRW(i), bg) == i ) | ||
ok1( BindCtxW (WithCtxRW(i), bg) == i ) | ||
ok1( BindCtxRW(WithCtxRW(i), bg) == i ) | ||
|
||
ok1( BindCtxR (WithCtxRC(i), bg) == i ) | ||
ok1( BindCtxRC(WithCtxRC(i), bg) == i ) | ||
|
||
ok1( BindCtxW (WithCtxWC(i), bg) == i ) | ||
ok1( BindCtxWC(WithCtxWC(i), bg) == i ) | ||
|
||
ok1( BindCtxR (WithCtxRWC(i), bg) == i ) | ||
ok1( BindCtxW (WithCtxRWC(i), bg) == i ) | ||
ok1( BindCtxRW (WithCtxRWC(i), bg) == i ) | ||
ok1( BindCtxRC (WithCtxRWC(i), bg) == i ) | ||
ok1( BindCtxWC (WithCtxRWC(i), bg) == i ) | ||
ok1( BindCtxRWC(WithCtxRWC(i), bg) == i ) | ||
} |