-
Notifications
You must be signed in to change notification settings - Fork 2
[M2] Add deadlines to Transport. #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nkryuchkov
wants to merge
27
commits into
skycoin:mainnet-milestone2
Choose a base branch
from
nkryuchkov:feature/transport-deadline
base: mainnet-milestone2
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
71eba71
Add deadlines to Transport
nkryuchkov ed38420
Improve logic of handling deadlines
nkryuchkov 1f20f25
Improve logic of handling deadlines
nkryuchkov a0d9802
Get rid of a goto
nkryuchkov 0169098
Implement deadline for pending i/o
nkryuchkov 7406640
Fix a typo
nkryuchkov aaf426e
Improve logic
nkryuchkov 808195d
Change implementation of deadlines
nkryuchkov 76f44b7
Fix uninitialized channels, improve implementation
nkryuchkov dadc93f
Add tests for deadlines
nkryuchkov a2cab90
Improve deadline tests names
nkryuchkov 7bc89e2
Run deadline tests in parallel
nkryuchkov 079158c
Add a test case
nkryuchkov 2d9aeee
Group deadline variables to a struct
nkryuchkov 0edd95a
Minor improvements
nkryuchkov 80a47c8
Add deadline.Serve
nkryuchkov d316c9e
Add deadlines checks before reading/writing
nkryuchkov 952c353
Make deadlines checks before reading/writing atomic
nkryuchkov a286d79
Fix issues
nkryuchkov bf6a935
Refactor deadlines
nkryuchkov cc5acf9
Fix a logic issue
nkryuchkov ade4248
Get rid of an else statement
nkryuchkov b50c331
Fix concurrency bugs
nkryuchkov 7583b23
Add basic tests for deadlines
nkryuchkov fb1edee
Fix naming and logic issues
nkryuchkov 08ec36e
Add a concurrent test for deadlines
nkryuchkov 29e4ddf
Merge remote-tracking branch 'upstream/mainnet-milestone1' into featu…
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 hidden or 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,78 @@ | ||
| package dmsg | ||
|
|
||
| import ( | ||
| "io" | ||
| "math" | ||
| "sync" | ||
| "sync/atomic" | ||
| "time" | ||
| ) | ||
|
|
||
| type deadline struct { | ||
| mu sync.Mutex | ||
| timestamp int64 | ||
| ch chan struct{} | ||
| modCh chan struct{} | ||
| modChClosed uint32 | ||
| } | ||
|
|
||
| func newDeadline() *deadline { | ||
| return &deadline{ | ||
| timestamp: math.MaxInt64, | ||
| ch: make(chan struct{}), | ||
| modCh: make(chan struct{}, 1), | ||
| } | ||
| } | ||
|
|
||
| func (d *deadline) Close() error { | ||
| d.mu.Lock() | ||
| defer d.mu.Unlock() | ||
|
|
||
| atomic.StoreUint32(&d.modChClosed, 1) | ||
| close(d.modCh) | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func (d *deadline) Set(t time.Time) error { | ||
| d.mu.Lock() | ||
| defer d.mu.Unlock() | ||
|
|
||
| if atomic.LoadUint32(&d.modChClosed) != 0 { | ||
| return io.ErrClosedPipe | ||
| } | ||
|
|
||
| atomic.StoreInt64(&d.timestamp, t.UnixNano()) | ||
| d.modCh <- struct{}{} | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func (d *deadline) Serve() error { | ||
| defer close(d.ch) | ||
| for { | ||
| if d.Exceeded() { | ||
| select { | ||
| case d.ch <- struct{}{}: | ||
| case _, ok := <-d.modCh: | ||
| if !ok { | ||
| return nil | ||
| } | ||
| } | ||
| continue | ||
| } | ||
| if _, ok := <-d.modCh; !ok { | ||
| return nil | ||
| } | ||
| } | ||
| } | ||
|
|
||
| func (d *deadline) Exceeded() bool { | ||
| now := time.Now().UnixNano() | ||
| deadline := atomic.LoadInt64(&d.timestamp) | ||
| return now >= deadline | ||
| } | ||
|
|
||
| func (d *deadline) Chan() <-chan struct{} { | ||
| return d.ch | ||
| } | ||
This file contains hidden or 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,133 @@ | ||
| package dmsg | ||
|
|
||
| import ( | ||
| "math" | ||
| "sync" | ||
| "testing" | ||
| "time" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func Test_newDeadline(t *testing.T) { | ||
| deadline := newDeadline() | ||
| require.NotNil(t, deadline) | ||
|
|
||
| require.EqualValues(t, math.MaxInt64, deadline.timestamp) | ||
| require.EqualValues(t, 0, deadline.modChClosed) | ||
|
|
||
| ch := deadline.ch | ||
| require.NotNil(t, ch) | ||
|
|
||
| modCh := deadline.modCh | ||
| require.NotNil(t, modCh) | ||
| } | ||
|
|
||
| func Test_deadline_SetDeadline(t *testing.T) { | ||
| deadline := newDeadline() | ||
|
|
||
| var wg sync.WaitGroup | ||
| var serveErr error | ||
| wg.Add(1) | ||
| go func() { | ||
| defer wg.Done() | ||
| serveErr = deadline.Serve() | ||
| }() | ||
|
|
||
| now := time.Now() | ||
| cases := []struct { | ||
| deadline time.Time | ||
| unixNano int64 | ||
| }{ | ||
| { | ||
| deadline: now.Add(1 * time.Second), | ||
| unixNano: now.Add(1 * time.Second).UnixNano(), | ||
| }, | ||
| { | ||
| deadline: now.Add(-1 * time.Second), | ||
| unixNano: now.Add(-1 * time.Second).UnixNano(), | ||
| }, | ||
| } | ||
|
|
||
| for _, tc := range cases { | ||
| require.NoError(t, deadline.Set(tc.deadline)) | ||
| require.Equal(t, tc.unixNano, deadline.timestamp) | ||
| } | ||
|
|
||
| require.NoError(t, deadline.Close()) | ||
| require.NotEqual(t, 0, deadline.modChClosed) | ||
|
|
||
| wg.Wait() | ||
| require.NoError(t, serveErr) | ||
| } | ||
|
|
||
| func Test_deadline_Chan(t *testing.T) { | ||
| deadline := newDeadline() | ||
| ch := deadline.Chan() | ||
| require.NotNil(t, ch) | ||
| } | ||
|
|
||
| func Test_deadline_Exceeded(t *testing.T) { | ||
| deadline := newDeadline() | ||
|
|
||
| var wg sync.WaitGroup | ||
| var serveErr error | ||
| wg.Add(1) | ||
| go func() { | ||
| defer wg.Done() | ||
| serveErr = deadline.Serve() | ||
| }() | ||
|
|
||
| now := time.Now() | ||
| cases := []struct { | ||
| deadline time.Time | ||
| exceeded bool | ||
| }{ | ||
| { | ||
| deadline: now.Add(1 * time.Second), | ||
| exceeded: false, | ||
| }, | ||
| { | ||
| deadline: now.Add(-1 * time.Second), | ||
| exceeded: true, | ||
| }, | ||
| } | ||
|
|
||
| for _, tc := range cases { | ||
| require.NoError(t, deadline.Set(tc.deadline)) | ||
| require.Equal(t, tc.exceeded, deadline.Exceeded()) | ||
| } | ||
|
|
||
| require.NoError(t, deadline.Close()) | ||
| require.NotEqual(t, 0, deadline.modChClosed) | ||
|
|
||
| wg.Wait() | ||
| require.NoError(t, serveErr) | ||
| } | ||
|
|
||
| func Test_deadline_concurrency(t *testing.T) { | ||
| t.Run("Set and close", func(t *testing.T) { | ||
| deadline := newDeadline() | ||
|
|
||
| var wg sync.WaitGroup | ||
| var serveErr error | ||
| wg.Add(1) | ||
| go func() { | ||
| defer wg.Done() | ||
| serveErr = deadline.Serve() | ||
| }() | ||
|
|
||
| var setErr error | ||
| wg.Add(1) | ||
| go func() { | ||
| defer wg.Done() | ||
| setErr = deadline.Set(time.Now().Add(1 * time.Second)) | ||
| }() | ||
|
|
||
| require.NoError(t, deadline.Close()) | ||
|
|
||
| wg.Wait() | ||
| require.NoError(t, serveErr) | ||
| require.Error(t, setErr) | ||
| }) | ||
| } |
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.