Skip to content
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

Add semantically blocking get in AtomicCell. #3635

Closed
smolp opened this issue May 16, 2023 · 6 comments
Closed

Add semantically blocking get in AtomicCell. #3635

smolp opened this issue May 16, 2023 · 6 comments

Comments

@smolp
Copy link

smolp commented May 16, 2023

I have a use case where I need to block possible incoming AtomicCell#get because of possibly long running evalUpdate.
Can we add it back, maybe as a new method on the AtomicCell?

@armanbilge
Copy link
Member

Thanks for opening the issue! We had a discussion about this topic in #3518 (comment). Would it be possible to explain your usecase in more detail?

@smolp
Copy link
Author

smolp commented May 16, 2023

Sure. I have multiple fs2 Streams running concurrently, accessing some AtomicCell.
One of those streams awakes periodically and has to perform a job on that AtomicCell, that can take some time or fail (just some cleanup operation, it just takes some time and if it fails then I just don't update with a new value) and no other stream must access the variable in the AtomicCell during that update.

The case is actually very similiar to the new test written in #3518 but you would expect to wait until the big IO finishes.

A very crude snippet would look like this:

        for {
          state <- AtomicCell[IO].of[Int](1)
          io1 = state.evalUpdate(state => IO.sleep(200.millis).map(_ => state + 50))
          io2 = IO.sleep(100.millis) *> state.get
          f1     <- io1.start
          result <- io2
          _      <- f1.joinWithNever
        } yield result shouldBe 51
    

@armanbilge
Copy link
Member

no other stream must access the variable in the AtomicCell during that update.

How do you handle this scenario? Wouldn't it break your semantics? Why or why not?

  1. fiber A gets the variable
  2. fiber B starts updating the variable
  3. fiber A uses the variable even though fiber B has started updating it

@smolp
Copy link
Author

smolp commented May 16, 2023

You are right, it would break in a general case like yours.
I have a safeguard inside the update that would prevent any unwanted behaviour, but in general case, where you get it right before an update starts, it could break, depending on what you want to do.

But what about the case if you want to pause gets during the update and just don't care what happens before because you e.g. safeguarded it inside your logic? Blocking get could be useful then?

@armanbilge
Copy link
Member

You are right, it would break in a general case like yours.

Right. AtomicCell does not have appropriate semantics for this use-case.

But what about the case if you want to pause gets during the update and just don't care what happens before because you e.g. safeguarded it inside your logic?

In that case, it sounds like you are designing a concurrent data structure with different semantics than AtomicCell 🙂

AtomicCell guarantees atomic, effectual updates. However, you are looking for a stronger semantic, which is exclusive access to a value i.e. while it is being used, no one can modify it, and while it is being modified, no one case use it. These semantics sound similar to the Lock proposed in #3542. Specifically, anyone modifying the value must acquire an "exclusive" lock to it, that waits until all other uses of the value have been released. See also https://github.com/davenverse/lock.

Another possibility to achieve these semantics: you can create a Hotswap with Resource.pure(...) and update it with swap(Resource.eval(...)). HotSwap#get guarantees that it will not be swapped while it is being used.

https://typelevel.org/cats-effect/api/3.x/cats/effect/std/Hotswap.html

@durban
Copy link
Contributor

durban commented May 23, 2023

If I understand correctly, the discussion concluded, that it's fine as it is, so I'll close this. (Feel free to reopen, if I'm misunderstanding.)

@durban durban closed this as not planned Won't fix, can't repro, duplicate, stale May 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants