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

io-sim: Fix flushTQueue implementation #135

Merged
merged 2 commits into from
Jan 31, 2024

Conversation

ch1bo
Copy link
Member

@ch1bo ch1bo commented Jan 30, 2024

Fixes #133 and also another issue found while fixing.

Now flushTQueue actually empties the queue and also maintains FIFO order.

Comment on lines 831 to 841
traceTQueueDefault
:: MonadTraceSTM m
=> proxy m
-> TQueueDefault m a
-> (Maybe [a] -> [a] -> InspectMonad m TraceValue)
-> STM m ()
traceTQueueDefault p (TQueue read write) f = do
traceTVar p read
(\mas as -> f mas as)
traceTVar p write
(\mas as -> f mas as)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong, because f has access to either side (read / write) of the queue, rather than all its elements. This is the reason why I kept the default implementation of TQueueDefault in a single TVar instead of two. This approach requires more substantial changes to io-sim.

I think it's much simpler to just fix flushTQueueDefault.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you suggest keeping the differing implementation using a single TVar? Why is tracing a deciding factor here - can't we implement this on the standard implementation of read/write end queues?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it is designed for verification purposes, so it's quite crucial for the library.

So you suggest keeping the differing implementation using a single TVar?

Yes, keep the current implementation which btw is based on a standard queue data type (see Okasaki's book). stm splits it into two TVar's I think for optimisation purposes, e.g. some operations will only need access one of the TVars which might change the contention in a parallel scenario - in io-sim we don't have any parallelism, so it's not a factor.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One invariant that one might want to be able to verify is the number of elements in a queue (if the application has such an invariant). It will be impossible to write it with the proposed traceTQueueDefault.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, let me try to write a flushTQueue which works on the single TVar.

I don't understand traceTQueueDefault and if you say we cannot implement it correctly for the standard double TVar implementation, I need to trust you.

But I do see the continued risk of maintaining a "differing" implementation on io-sim which does not correspond to the IO/STM variant semantics - if we could "just" keep lifted copies of the base and stm implementations around, that would be much more maintainable by casual contributors like me.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in ch1bo@9e2444d, but while doing so I discovered another bug (which underlines my worry of having non-standard implementation): #136

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it not make sense to have an "equivalence property" written for all io-sim functions that "guarantees" the semantics is consistent with what's provided by the IO instance?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@abailly-iohk that's a good idea.

Copy link
Collaborator

@coot coot Jan 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I created an issue for this: #137.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand traceTQueueDefault and if you say we cannot implement it correctly for the standard double TVar implementation, I need to trust you.

Just for the sake of explanation:

traceTVar guarantees that its callback is called when the TVar is committed in an stm transaction and receives the current (and previous) data stored in the TVar. If TQueueDefault is using two TVars io-sim will need to know that not only the committed TVar matters but also the other one. That's the reason why two TVars are problematic.

traceTVar is designed for writing properties when order of events matters but one cannot relay on order of trace messages (i.e. in concurrent scenario order of trace messages will depend on the scheduler). traceTVar callbacks are guaranteed to be called right after an atomic transaction is committed in this since they do not depend on the scheduler. If you do readTVarIO >>= traceM . show, io-sim will deschedule the thread after readTVarIO and you're no longer guaranteed that multiple concurrent traceM calls will be done in the same order as the atomic transactions.

@ch1bo ch1bo requested a review from coot January 30, 2024 11:23
@ch1bo ch1bo changed the title Remove wrong implementation of TQueue in io-sim io-sim: Fix flushTQueue implementation Jan 30, 2024
@ch1bo ch1bo force-pushed the fix-flushtqueue branch 2 times, most recently from 614974d to 9e2444d Compare January 30, 2024 11:36
@ch1bo
Copy link
Member Author

ch1bo commented Jan 30, 2024

All comments addressed on this one @coot

io-sim/src/Control/Monad/IOSim/STM.hs Outdated Show resolved Hide resolved
Copy link
Collaborator

@coot coot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@coot coot added this pull request to the merge queue Jan 31, 2024
Merged via the queue into input-output-hk:main with commit abe7810 Jan 31, 2024
17 checks passed
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

Successfully merging this pull request may close these issues.

flushTQueue is broken
3 participants