-
Couldn't load subscription status.
- Fork 1.4k
Prototype Safe Semaphore #1523
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
Prototype Safe Semaphore #1523
Conversation
…, &> (#1510) * Add ZStrem#zip left and right operators and alias for all zip operators * formatted code to make scalafmtCheck pass. * change for <*> variants with flatmap and <&> with zipWith. * adding crossWith and cross functions to ZStream. * merge conflict change. * formatted naming conventions.
|
This could use some feedback if we want to do anything on it for the 1.0 release. |
| semaphore <- Semaphore.make(n) | ||
| available <- IO.foreach((0L until n).toList)(_ => semaphore.acquire) *> semaphore.available | ||
| } yield available must_=== 0) | ||
| available <- IO.foreach((0L until n).toList)(_ => semaphore.withPermit(semaphore.available)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes me want to add a semaphore.withAllPermits
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... nothing to do with the test though, just thought that one might want a monopoly over all permits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, if we went with this approach we could definitely maintain a val with the total number of permits and expose a withAllPermits method.
| --- | ||
|
|
||
| A `Semaphore` datatype which allows synchronization between fibers with `acquire` and `release` operations. | ||
| A `Semaphore` datatype which allows synchronization between fibers with the `withPermit` operation, which safely acquires and releases a permit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that it is still possible to trick the system by asking for a negative number of permits.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't assertNonNegative cause the fiber to die at that point?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, on release, which seems wrong 🤔 It's like catching a bad guy when it's too late 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. Yes we could definitely fix that.
|
You have my vote, I'd just like to clarify the behaviour when passing a negative number (right now |
|
@regiskuckaertz I added a fix for this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love it. I think I would move the assertNonNegative out of prepare and release now, as ostensibly the latter would never get evaluated anyway.
|
@regiskuckaertz Sorry, don't we need it in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes of course 🤦♂️ This is great!
|
@jdegoes When you have the chance could I get some feedback on whether you want to move forward with this? If so I think the next steps would be adding a couple of convenience methods on |
| * If the specified number of permits are not available, the fiber invoking | ||
| * this method will be suspended until the permits are available. | ||
| * | ||
| * Ported from @mpilquist work in Cats Effect (https://github.com/typelevel/cats-effect/pull/403) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should preserve this attribution comment in any case.
| /** | ||
| * Releases a single permit. | ||
| */ | ||
| final def release: UIO[Unit] = releaseN(1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because code uses these functions, we should at least deprecate them until 1.0.
|
I incorporated your comments. The changes are pretty small at this point, just deprecating the methods on |
|
@jdegoes Sorry could you approve one more time? Had to resolve a merge conflict. |
|
@regiskuckaertz Thanks! |
* implement permits * make TRef state private * prototype safe semaphore * implement permits * make TRef state private * zio#1219 - add doUntilEquals and doWhileEquals methods (zio#1634) * Update zio-interop-reactivestreams to 1.0.3.1-RC1 (zio#1665) * Add ZStream#cross, crossWith, <*>, <*, *>, <&>, zipLeft, zipRight, <&, &> (zio#1510) * Add ZStrem#zip left and right operators and alias for all zip operators * formatted code to make scalafmtCheck pass. * change for <*> variants with flatmap and <&> with zipWith. * adding crossWith and cross functions to ZStream. * merge conflict change. * formatted naming conventions. * Update the encoding of ZSink (zio#1560) * prototype safe semaphore * cleanup * uodate documentation * address review comments * cleanup * add back and deprecate methods * cleanup * make method private
Resolves #1511. We actually didn't keep track of the number of permits before because it didn't matter as long as we started out with a certain number and didn't leak them. I added a value to record the number of permits. Change required was very minimal.
Only other thing to think about is in the case of
TRefI had to abandon it extendingAnyValbecause now it has two parameters. We could try go put the value in theTRefinstead or put them both in a case class but I think we lose as much as we gain that way.