@@ -353,24 +353,27 @@ writeStepsPerformed (StepsPerformedVar v) x = writePrimVar v x
353
353
Credits
354
354
-> CreditThreshold
355
355
-> Ref (MergingRun IO h)
356
- -> IO () #-}
356
+ -> IO Credits #-}
357
357
-- | Supply the given amount of credits to a merging run. This /may/ cause an
358
358
-- ongoing merge to progress.
359
359
supplyCredits ::
360
360
forall m h . (MonadSTM m , MonadST m , MonadMVar m , MonadMask m )
361
361
=> Credits
362
362
-> CreditThreshold
363
363
-> Ref (MergingRun m h )
364
- -> m ()
364
+ -> m Credits
365
365
supplyCredits (Credits c) creditsThresh (DeRef MergingRun {.. }) = do
366
366
mergeCompleted <- readMutVar mergeKnownCompleted
367
367
368
368
-- The merge is already finished
369
369
if mergeCompleted == MergeKnownCompleted then
370
- pure ()
370
+ -- we're already done so all supplied credits are leftovers
371
+ pure (Credits c)
371
372
else do
372
373
-- unspentCredits' is our /estimate/ of what the new total of unspent
373
- -- credits is.
374
+ -- credits is. It is an estimate due to potential concurrency: other
375
+ -- threads may also by supplying credits. We only check the credit
376
+ -- balance once, which is the result of addUnspentCredits here:
374
377
Credits unspentCredits' <- addUnspentCredits mergeUnspentCreditsVar (Credits c)
375
378
stepsPerformed <- readStepsPerformed mergeStepsPerformedVar
376
379
@@ -382,6 +385,9 @@ supplyCredits (Credits c) creditsThresh (DeRef MergingRun {..}) = do
382
385
(stepMerge mergeSpentCreditsVar mergeStepsPerformedVar
383
386
mergeState)
384
387
when isMergeDone $ completeMerge mergeState mergeKnownCompleted
388
+ let ! leftoverCredits = stepsPerformed + unspentCredits'
389
+ - unNumEntries mergeNumEntries
390
+ return (Credits leftoverCredits)
385
391
else if unspentCredits' >= getCreditThreshold creditsThresh then do
386
392
-- We can do some merging work without finishing the merge immediately
387
393
isMergeDone <-
@@ -405,9 +411,14 @@ supplyCredits (Credits c) creditsThresh (DeRef MergingRun {..}) = do
405
411
-- completion, then that is fine. The next supplyCredits will
406
412
-- complete the merge.
407
413
when isMergeDone $ completeMerge mergeState mergeKnownCompleted
414
+ -- We return 0 credits here, even if we completed the merge. This is
415
+ -- because if we did complete the merge, it was due to other threads
416
+ -- supplying credits, not due to the credits we supplied here.
417
+ return (Credits 0 )
408
418
else
409
- -- Just accumulate credits, because we are not over the threshold yet
410
- pure ()
419
+ -- Just accumulate credits, because we are not over the threshold yet.
420
+ -- Thus no leftover credits.
421
+ pure (Credits 0 )
411
422
412
423
{-# SPECIALISE addUnspentCredits ::
413
424
UnspentCreditsVar RealWorld
@@ -512,11 +523,12 @@ stepMerge spentCreditsVar stepsPerformedVar mergeVar (Credits c) =
512
523
CompletedMerge {} -> pure False
513
524
(OngoingMerge _rs m) -> do
514
525
stepsPerformed <- readStepsPerformed stepsPerformedVar
515
- spentCredits <- readSpentCredits spentCreditsVar
526
+ spentCredits <- readSpentCredits spentCreditsVar
516
527
517
528
-- If we previously performed too many merge steps, then we perform
518
529
-- fewer now.
519
- let stepsToDo = max 0 (spentCredits + c - stepsPerformed)
530
+ let stepsSurplus = stepsPerformed - spentCredits
531
+ stepsToDo = max 0 (c - stepsSurplus)
520
532
-- Merge.steps guarantees that @stepsDone >= stepsToDo@ /unless/ the
521
533
-- merge was just now finished.
522
534
(stepsDone, stepResult) <- Merge. steps m stepsToDo
0 commit comments