-
Notifications
You must be signed in to change notification settings - Fork 53
feat: add AsyncSemaphore #586
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
Merged
Merged
Changes from 14 commits
Commits
Show all changes
22 commits
Select commit
Hold shift + click to select a range
3a40a3c
initial commit
vladopajic 78e54d8
fix test
vladopajic dd95d32
improvements
vladopajic 9d5001d
Update chronos/asyncsync.nim
vladopajic 14d3db6
improvement
vladopajic f5047d6
remove forceAcquire
vladopajic 0cb047c
remove count
vladopajic 287cec6
test improvements
vladopajic cc50060
Merge branch 'master' into semaphore2
vladopajic 64f2a4a
Merge branch 'master' into semaphore2
vladopajic 774aaa9
code review changes
vladopajic 0b84a35
Merge branch 'master' into semaphore2
vladopajic fb0034e
acquire ho cancel
vladopajic 90f3b2d
raise AsyncSemaphoreError
vladopajic fcb360b
Update chronos/asyncsync.nim
vladopajic 686e3bd
Update chronos/asyncsync.nim
vladopajic a640afe
Merge branch 'master' into semaphore2
vladopajic ecd9ca7
ingore cancelled futures
vladopajic bb1b4bc
Merge branch 'master' into semaphore2
vladopajic 9fdd4f9
queue -> waiters
vladopajic cf4b063
Merge branch 'semaphore2' of github.com:status-im/nim-chronos into se…
vladopajic 5a5b87f
Update chronos/asyncsync.nim
vladopajic 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
Some comments aren't visible on the classic Files Changed page.
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
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,161 @@ | ||
| # Chronos Test Suite | ||
| # (c) Copyright 2018-Present | ||
| # Status Research & Development GmbH | ||
| # | ||
| # Licensed under either of | ||
| # Apache License, version 2.0, (LICENSE-APACHEv2) | ||
| # MIT license (LICENSE-MIT) | ||
| import unittest2 | ||
| import ../chronos, ../chronos/unittest2/asynctests | ||
|
|
||
| {.used.} | ||
|
|
||
| suite "AsyncSemaphore": | ||
| teardown: | ||
| checkLeaks() | ||
|
|
||
| asyncTest "default size": | ||
| let sema = newAsyncSemaphore() | ||
| check sema.availableSlots == 1 | ||
|
|
||
| asyncTest "custom size": | ||
| let sema = newAsyncSemaphore(3) | ||
| check sema.availableSlots == 3 | ||
|
|
||
| asyncTest "invalid size": | ||
| expect AssertionDefect: | ||
| discard newAsyncSemaphore(0) | ||
|
|
||
| asyncTest "should acquire": | ||
| let sema = newAsyncSemaphore(3) | ||
|
|
||
| await sema.acquire() | ||
| check sema.availableSlots == 2 | ||
| await sema.acquire() | ||
| check sema.availableSlots == 1 | ||
| await sema.acquire() | ||
| check sema.availableSlots == 0 | ||
|
|
||
| asyncTest "should release": | ||
| let sema = newAsyncSemaphore(3) | ||
|
|
||
| await sema.acquire() | ||
| await sema.acquire() | ||
| await sema.acquire() | ||
|
|
||
| sema.release() | ||
| check sema.availableSlots == 1 | ||
| sema.release() | ||
| check sema.availableSlots == 2 | ||
| sema.release() | ||
| check sema.availableSlots == 3 | ||
|
|
||
| asyncTest "initial release": | ||
| let sema = newAsyncSemaphore(3) | ||
|
|
||
| expect AsyncSemaphoreError: # should not release | ||
| sema.release() | ||
|
|
||
| asyncTest "double release": | ||
| let sema = newAsyncSemaphore(3) | ||
|
|
||
| await sema.acquire() | ||
| sema.release() | ||
| expect AsyncSemaphoreError: # should not release | ||
| sema.release() | ||
|
|
||
| asyncTest "should queue acquire": | ||
| let sema = newAsyncSemaphore(1) | ||
|
|
||
| await sema.acquire() | ||
| let fut = sema.acquire() | ||
|
|
||
| check sema.availableSlots == 0 | ||
| sema.release() | ||
| sema.release() | ||
|
|
||
| await fut | ||
| check fut.finished() | ||
|
|
||
| asyncTest "should tryAcquire": | ||
| let sema = newAsyncSemaphore(1) | ||
| await sema.acquire() | ||
| check sema.tryAcquire() == false | ||
|
|
||
| asyncTest "should tryAcquire and acquire": | ||
| let sema = newAsyncSemaphore(4) | ||
| check sema.tryAcquire() == true | ||
| check sema.tryAcquire() == true | ||
| check sema.tryAcquire() == true | ||
| check sema.tryAcquire() == true | ||
| check sema.availableSlots == 0 | ||
|
|
||
| let fut = sema.acquire() | ||
| check fut.finished == false | ||
| check sema.availableSlots == 0 | ||
|
|
||
| sema.release() | ||
| sema.release() | ||
| sema.release() | ||
| sema.release() | ||
| sema.release() | ||
|
|
||
| check fut.finished == true | ||
| check sema.availableSlots == 4 | ||
|
|
||
| asyncTest "should cancel sequential semaphore slot": | ||
| let sema = newAsyncSemaphore(1) | ||
|
|
||
| await sema.acquire() | ||
|
|
||
| let | ||
| tmp = sema.acquire() | ||
| tmp2 = sema.acquire() | ||
| check: | ||
| not tmp.finished() | ||
| not tmp2.finished() | ||
|
|
||
| tmp.cancel() | ||
| sema.release() | ||
|
|
||
| check tmp2.finished() | ||
|
|
||
| sema.release() | ||
|
|
||
| check await sema.acquire().withTimeout(10.millis) | ||
|
|
||
| asyncTest "should handle out of order cancellations": | ||
| let sema = newAsyncSemaphore(1) | ||
|
|
||
| await sema.acquire() # 1st acquire | ||
| let tmp1 = sema.acquire() # 2nd acquire | ||
| check not tmp1.finished() | ||
|
|
||
| let tmp2 = sema.acquire() # 3rd acquire | ||
| check not tmp2.finished() | ||
|
|
||
| let tmp3 = sema.acquire() # 4th acquire | ||
| check not tmp3.finished() | ||
|
|
||
| # up to this point, we've called acquire 4 times | ||
| tmp1.cancel() # 1st release (implicit) | ||
| tmp2.cancel() # 2nd release (implicit) | ||
|
|
||
| check not tmp3.finished() # check that we didn't release the wrong slot | ||
|
|
||
| sema.release() # 3rd release (explicit) | ||
| check tmp3.finished() | ||
|
|
||
| sema.release() # 4th release | ||
| check await sema.acquire().withTimeout(10.millis) | ||
|
|
||
| asyncTest "should properly handle timeouts and cancellations": | ||
| let sema = newAsyncSemaphore(1) | ||
|
|
||
| await sema.acquire() | ||
| check not (await sema.acquire().withTimeout(1.millis)) | ||
| # should not acquire but cancel | ||
| sema.release() | ||
|
|
||
| check await sema.acquire().withTimeout(10.millis) | ||
|
|
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.