-
Notifications
You must be signed in to change notification settings - Fork 511
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
Make HotSwap
safe to concurrent access
#3480
Conversation
* For safer access to the current resource see [[get]], which guarantees that it will not be | ||
* released while it is being used. | ||
* | ||
* If [[swap]] is called after the lifetime of the [[Hotswap]] is over, it will raise an | ||
* error, but will ensure that all resources are finalized before returning. | ||
*/ | ||
def swap(next: Resource[F, R]): F[R] |
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.
This API is a bit unsafey since it directly returns the R
but I think we'll just have to live with that.
/** | ||
* Gets the current resource, if it exists. The returned resource is guaranteed to be | ||
* available for the duration of the returned resource. | ||
*/ | ||
def get: Resource[F, Option[R]] |
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.
Maybe a little bit annoying UX that this is an Option[R]
, alternatively we could raise an error. But the user can decide to do that too.
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.
Bikeshed the name. access
a la HotswapRef
?
Woops, I didn't think this through :) we need to make sure that multiple readers don't block each other. |
Co-authored-by: catostrophe <40268503+catostrophe@users.noreply.github.com>
def shared: Resource[F, Unit] = semaphore.permit | ||
|
||
def exclusive: Resource[F, Unit] = | ||
Resource.makeFull[F, Unit](poll => poll(semaphore.acquireN(Long.MaxValue)))(_ => | ||
semaphore.releaseN(Long.MaxValue)) |
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.
Stole this from here:
https://github.com/janstenpickle/hotswap-ref/blob/34781a0af15784981cd007b74f0f5c31836d73f3/modules/core/src/main/scala/io/janstenpickle/hotswapref/Lock.scala
It seems like a good addition to std
on its own merits.
trait Lock[F[_]] {
def shared: Resource[F, Unit]
def exclusive: Resource[F, Unit]
}
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.
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.
Lock
would probably be a good addition, but the tricky bit is that it isn't reentrant, so we have to be really careful.
def shared: Resource[F, Unit] = semaphore.permit | ||
|
||
def exclusive: Resource[F, Unit] = | ||
Resource.makeFull[F, Unit](poll => poll(semaphore.acquireN(Long.MaxValue)))(_ => | ||
semaphore.releaseN(Long.MaxValue)) |
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.
Lock
would probably be a good addition, but the tricky bit is that it isn't reentrant, so we have to be really careful.
Fixes #2050. Closes #3473.
The current resource in
Hotswap
is now guarded by a mutex, which must be acquired to swap or clear it. A new methodget
also provides safe access to the current resource, by acquiring the mutex while it is in use.