packages feed

wireform-core-0.2.0.0: src/Wireform/Ring.hs

{-# LANGUAGE CApiFFI #-}
{-# LANGUAGE RankNTypes #-}

{- | Double-mapped (\"magic\") ring buffer.

A buffer of size @N@ (power of two, page-aligned) backed by a single
shared-memory object mapped twice into a contiguous @2N@-byte virtual
region.  Any read of up to @N@ bytes starting anywhere in
@[base, base + N)@ is contiguous in virtual memory — the MMU handles
the wrap transparently.

The parser's pointer-bumping primitives rely on this property: they
never contain wrap logic.

== Scoping

'MagicRing' carries a phantom type parameter @s@ that works like the
@s@ on 'Control.Monad.ST.ST'.  'withMagicRing' is rank-2:

> withMagicRing :: Int -> (forall s. MagicRing s -> IO a) -> IO a

Slices produced from the ring ('RingSlice') inherit @s@ and therefore
cannot appear in @a@ — they are unable to outlive the buffer that
backs them and would otherwise alias bytes that subsequent refills
overwrite.  When a slice has to leave the scope, 'copyRingSlice'
materialises a fresh 'ByteString' by memcpy.
-}
module Wireform.Ring (
  -- * The ring
  MagicRing,
  withMagicRing,
  ringBase,
  ringSize,
  ringMask,
  MagicRingException (..),

  -- * Slices
  RingSlice,
  ringSlice,
  ringSliceAtPos,
  ringSliceLength,
  withRingSlice,
  peekRingSliceByte,
  copyRingSlice,
) where

import Wireform.Ring.Internal