diff options
Diffstat (limited to 'src/Network/WireGuard/Internal/PacketQueue.hs')
-rw-r--r-- | src/Network/WireGuard/Internal/PacketQueue.hs | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/src/Network/WireGuard/Internal/PacketQueue.hs b/src/Network/WireGuard/Internal/PacketQueue.hs new file mode 100644 index 0000000..bc390f8 --- /dev/null +++ b/src/Network/WireGuard/Internal/PacketQueue.hs @@ -0,0 +1,49 @@ +{-# LANGUAGE RecordWildCards #-} + +module Network.WireGuard.Internal.PacketQueue + ( PacketQueue + , newPacketQueue + , popPacketQueue + , pushPacketQueue + , tryPushPacketQueue + ) where + +import Control.Concurrent.STM + +data PacketQueue packet = PacketQueue + { tqueue :: TQueue packet + , allowance :: TVar Int + } + +-- | Create a new PacketQueue with size limit of |maxQueuedPackets|. +newPacketQueue :: Int -> STM (PacketQueue packet) +newPacketQueue maxQueuedPackets = PacketQueue <$> newTQueue <*> newTVar maxQueuedPackets + +-- | Pop a packet out from the queue, blocks if no packet is available. +popPacketQueue :: PacketQueue packet -> STM packet +popPacketQueue PacketQueue{..} = do + packet <- readTQueue tqueue + modifyTVar' allowance (+1) + return packet + +-- | Push a packet into the queue. Blocks if it's full. +pushPacketQueue :: PacketQueue packet -> packet -> STM () +pushPacketQueue PacketQueue{..} packet = do + allowance' <- readTVar allowance + if allowance' <= 0 + then retry + else do + writeTQueue tqueue packet + writeTVar allowance (allowance' - 1) + +-- | Try to push a packet into the queue. Returns True if it's pushed. +tryPushPacketQueue :: PacketQueue packet -> packet -> STM Bool +tryPushPacketQueue PacketQueue{..} packet = do + allowance' <- readTVar allowance + if allowance' <= 0 + then return False + else do + writeTQueue tqueue packet + writeTVar allowance (allowance' - 1) + return True + |