Commit a0b4a2ac authored by Edward Z. Yang's avatar Edward Z. Yang

Rename compact to ghc-compact.

Summary:
The plan is to release a separate library, 'compact', which gives a
friendly user-facing interface.  This library is just enough so that we
can make sure the functionality is working in GHC.
Signed-off-by: default avatarEdward Z. Yang <ezyang@cs.stanford.edu>

Test Plan: validate

Reviewers: bgamari, dfeuer, austin, simonmar, hvr

Subscribers: thomie, erikd, snowleopard

Differential Revision: https://phabricator.haskell.org/D3206
parent 8f20844d
......@@ -1106,7 +1106,7 @@ AC_SUBST(BUILD_SPHINX_PDF)
LIBRARY_VERSION(base)
LIBRARY_VERSION(Cabal, Cabal/Cabal)
LIBRARY_VERSION(ghc-prim)
LIBRARY_VERSION(compact)
LIBRARY_VERSION(ghc-compact)
LIBRARY_ghc_VERSION="$ProjectVersion"
AC_SUBST(LIBRARY_ghc_VERSION)
......
......@@ -463,7 +463,7 @@ PACKAGES_STAGE1 += ghc-boot
PACKAGES_STAGE1 += template-haskell
PACKAGES_STAGE1 += hoopl
PACKAGES_STAGE1 += transformers
PACKAGES_STAGE1 += compact
PACKAGES_STAGE1 += ghc-compact
ifeq "$(HADDOCK_DOCS)" "YES"
PACKAGES_STAGE1 += xhtml
......
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.Compact.Internal
-- Copyright : (c) The University of Glasgow 2001-2009
-- (c) Giovanni Campagna <gcampagn@cs.stanford.edu> 2015
-- License : BSD-style (see the file LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : unstable
-- Portability : non-portable (GHC Extensions)
--
-- This module provides some internal functions and representation for dealing
-- with compact regions, which may be of interest if you need higher
-- performance.
--
-- /Since: 1.0.0/
module Data.Compact.Internal
( Compact(..)
, mkCompact
, compactSized
) where
import Control.Concurrent.MVar
import GHC.Prim
import GHC.Types
-- | A 'Compact' contains fully evaluated, pure, immutable data.
--
-- 'Compact' serves two purposes:
--
-- * Data stored in a 'Compact' has no garbage collection overhead.
-- The garbage collector considers the whole 'Compact' to be alive
-- if there is a reference to any object within it.
--
-- * A 'Compact' can be serialized, stored, and deserialized again.
-- The serialized data can only be deserialized by the exact binary
-- that created it, but it can be stored indefinitely before
-- deserialization.
--
-- Compacts are self-contained, so compacting data involves copying
-- it; if you have data that lives in two 'Compact's, each will have a
-- separate copy of the data.
--
-- The cost of compaction is similar to the cost of GC for the same
-- data, but it is perfomed only once. However, because
-- "Data.Compact.compact" does not stop-the-world, retaining internal
-- sharing during the compaction process is very costly. The user
-- can choose wether to 'compact' or 'compactWithSharing'.
--
-- When you have a @'Compact' a@, you can get a pointer to the actual object
-- in the region using "Data.Compact.getCompact". The 'Compact' type
-- serves as handle on the region itself; you can use this handle
-- to add data to a specific 'Compact' with 'compactAdd' or
-- 'compactAddWithSharing' (giving you a new handle which corresponds
-- to the same compact region, but points to the newly added object
-- in the region). At the moment, due to technical reasons,
-- it's not possible to get the @'Compact' a@ if you only have an @a@,
-- so make sure you hold on to the handle as necessary.
--
-- Data in a compact doesn't ever move, so compacting data is also a
-- way to pin arbitrary data structures in memory.
--
-- There are some limitations on what can be compacted:
--
-- * Functions. Compaction only applies to data.
--
-- * Pinned 'ByteArray#' objects cannot be compacted. This is for a
-- good reason: the memory is pinned so that it can be referenced by
-- address (the address might be stored in a C data structure, for
-- example), so we can't make a copy of it to store in the 'Compact'.
--
-- * Objects with mutable pointer fields also cannot be compacted,
-- because subsequent mutation would destroy the property that a compact is
-- self-contained.
--
-- If compaction encounters any of the above, a 'CompactionFailed'
-- exception will be thrown by the compaction operation.
--
data Compact a = Compact Compact# a (MVar ())
-- we can *read* from a Compact without taking a lock, but only
-- one thread can be writing to the compact at any given time.
-- The MVar here is to enforce mutual exclusion among writers.
-- Note: the MVar protects the Compact# only, not the pure value 'a'
-- | Make a new 'Compact' object, given a pointer to the true
-- underlying region. You must uphold the invariant that @a@ lives
-- in the compact region.
--
mkCompact
:: Compact# -> a -> State# RealWorld -> (# State# RealWorld, Compact a #)
mkCompact compact# a s =
case unIO (newMVar ()) s of { (# s1, lock #) ->
(# s1, Compact compact# a lock #) }
where
unIO (IO a) = a
-- | Transfer @a@ into a new compact region, with a preallocated size,
-- possibly preserving sharing or not. If you know how big the data
-- structure in question is, you can save time by picking an appropriate
-- block size for the compact region.
--
compactSized :: Int -> Bool -> a -> IO (Compact a)
compactSized (I# size) share a = IO $ \s0 ->
case compactNew# (int2Word# size) s0 of { (# s1, compact# #) ->
case compactAddPrim compact# a s1 of { (# s2, pk #) ->
mkCompact compact# pk s2 }}
where
compactAddPrim
| share = compactAddWithSharing#
| otherwise = compactAdd#
......@@ -6,7 +6,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : Data.Compact
-- Module : GHC.Compact
-- Copyright : (c) The University of Glasgow 2001-2009
-- (c) Giovanni Campagna <gcampagn@cs.stanford.edu> 2014
-- License : BSD-style (see the file LICENSE)
......@@ -57,9 +57,9 @@
--
-- This library is supported by GHC 8.2 and later.
module Data.Compact (
module GHC.Compact (
-- * The Compact type
Compact,
Compact(..),
-- * Compacting data
compact,
......@@ -75,13 +75,100 @@ module Data.Compact (
-- * Other utilities
compactResize,
-- * Internal operations
mkCompact,
compactSized,
) where
import Control.Concurrent
import Control.Concurrent.MVar
import GHC.Prim
import GHC.Types
import Data.Compact.Internal as Internal
-- | A 'Compact' contains fully evaluated, pure, immutable data.
--
-- 'Compact' serves two purposes:
--
-- * Data stored in a 'Compact' has no garbage collection overhead.
-- The garbage collector considers the whole 'Compact' to be alive
-- if there is a reference to any object within it.
--
-- * A 'Compact' can be serialized, stored, and deserialized again.
-- The serialized data can only be deserialized by the exact binary
-- that created it, but it can be stored indefinitely before
-- deserialization.
--
-- Compacts are self-contained, so compacting data involves copying
-- it; if you have data that lives in two 'Compact's, each will have a
-- separate copy of the data.
--
-- The cost of compaction is similar to the cost of GC for the same
-- data, but it is perfomed only once. However, because
-- "Data.Compact.compact" does not stop-the-world, retaining internal
-- sharing during the compaction process is very costly. The user
-- can choose wether to 'compact' or 'compactWithSharing'.
--
-- When you have a @'Compact' a@, you can get a pointer to the actual object
-- in the region using "Data.Compact.getCompact". The 'Compact' type
-- serves as handle on the region itself; you can use this handle
-- to add data to a specific 'Compact' with 'compactAdd' or
-- 'compactAddWithSharing' (giving you a new handle which corresponds
-- to the same compact region, but points to the newly added object
-- in the region). At the moment, due to technical reasons,
-- it's not possible to get the @'Compact' a@ if you only have an @a@,
-- so make sure you hold on to the handle as necessary.
--
-- Data in a compact doesn't ever move, so compacting data is also a
-- way to pin arbitrary data structures in memory.
--
-- There are some limitations on what can be compacted:
--
-- * Functions. Compaction only applies to data.
--
-- * Pinned 'ByteArray#' objects cannot be compacted. This is for a
-- good reason: the memory is pinned so that it can be referenced by
-- address (the address might be stored in a C data structure, for
-- example), so we can't make a copy of it to store in the 'Compact'.
--
-- * Objects with mutable pointer fields also cannot be compacted,
-- because subsequent mutation would destroy the property that a compact is
-- self-contained.
--
-- If compaction encounters any of the above, a 'CompactionFailed'
-- exception will be thrown by the compaction operation.
--
data Compact a = Compact Compact# a (MVar ())
-- we can *read* from a Compact without taking a lock, but only
-- one thread can be writing to the compact at any given time.
-- The MVar here is to enforce mutual exclusion among writers.
-- Note: the MVar protects the Compact# only, not the pure value 'a'
-- | Make a new 'Compact' object, given a pointer to the true
-- underlying region. You must uphold the invariant that @a@ lives
-- in the compact region.
--
mkCompact
:: Compact# -> a -> State# RealWorld -> (# State# RealWorld, Compact a #)
mkCompact compact# a s =
case unIO (newMVar ()) s of { (# s1, lock #) ->
(# s1, Compact compact# a lock #) }
where
unIO (IO a) = a
-- | Transfer @a@ into a new compact region, with a preallocated size,
-- possibly preserving sharing or not. If you know how big the data
-- structure in question is, you can save time by picking an appropriate
-- block size for the compact region.
--
compactSized :: Int -> Bool -> a -> IO (Compact a)
compactSized (I# size) share a = IO $ \s0 ->
case compactNew# (int2Word# size) s0 of { (# s1, compact# #) ->
case compactAddPrim compact# a s1 of { (# s2, pk #) ->
mkCompact compact# pk s2 }}
where
compactAddPrim
| share = compactAddWithSharing#
| otherwise = compactAdd#
-- | Retrieve a direct pointer to the value pointed at by a 'Compact' reference.
-- If you have used 'compactAdd', there may be multiple 'Compact' references
......@@ -104,7 +191,7 @@ getCompact (Compact _ obj _) = obj
-- class which will help statically check if this is the case or not.
--
compact :: a -> IO (Compact a)
compact = Internal.compactSized 31268 False
compact = compactSized 31268 False
-- | Compact a value, retaining any internal sharing and
-- cycles. /O(size of data)/
......@@ -118,7 +205,7 @@ compact = Internal.compactSized 31268 False
-- class which will help statically check if this is the case or not.
--
compactWithSharing :: a -> IO (Compact a)
compactWithSharing = Internal.compactSized 31268 True
compactWithSharing = compactSized 31268 True
-- | Add a value to an existing 'Compact'. This will help you avoid
-- copying when the value contains pointers into the compact region,
......
......@@ -5,7 +5,7 @@
-----------------------------------------------------------------------------
-- |
-- Module : Data.Compact.Serialized
-- Module : GHC.Compact.Serialized
-- Copyright : (c) The University of Glasgow 2001-2009
-- (c) Giovanni Campagna <gcampagn@cs.stanford.edu> 2015
-- License : BSD-style (see the file LICENSE)
......@@ -19,7 +19,7 @@
--
-- /Since: 1.0.0/
module Data.Compact.Serialized(
module GHC.Compact.Serialized(
SerializedCompact(..),
withSerializedCompact,
importCompact,
......@@ -39,7 +39,7 @@ import Data.IORef(newIORef, readIORef, writeIORef)
import Foreign.ForeignPtr(withForeignPtr)
import Foreign.Marshal.Utils(copyBytes)
import Data.Compact.Internal
import GHC.Compact
-- | A serialized version of the 'Compact' metadata (each block with
-- address and size and the address of the root). This structure is
......
name: compact
version: 1.0.0.0
name: ghc-compact
version: 0.1.0.0
-- NOTE: Don't forget to update ./changelog.md
license: BSD3
license-file: LICENSE
maintainer: libraries@haskell.org
bug-reports: http://ghc.haskell.org/trac/ghc/newticket?component=libraries/compact
bug-reports: http://ghc.haskell.org/trac/ghc/newticket?component=libraries/ghc-compact
synopsis: In memory storage of deeply evaluated data structure
category: Data
description:
This package provides a single data structure, called a Compact,
which holds a single haskell object in fully evaluated form. The
invariant is, no pointers live inside the struct that point outside
it, which ensures efficient garbage collection without ever reading
the structure contents (effectively, it works as a manually managed
"oldest generation" which is never freed until the whole is released).
This package provides minimal functionality for working with
"compact regions", which hold a fully evaluated Haskell object graph.
These regions maintain the invariant that no pointers live inside the struct
that point outside it, which ensures efficient garbage collection without
ever reading the structure contents (effectively, it works as a manually
managed "oldest generation" which is never freed until the whole is
released).
Internally, the struct is stored a single contiguous block of memory,
which allows efficient serialization and deserialization of structs
......@@ -25,7 +26,7 @@ tested-with: GHC==7.11
source-repository head
type: git
location: http://git.haskell.org/ghc.git
subdir: libraries/compact
subdir: libraries/ghc-compact
library
default-language: Haskell2010
......@@ -40,6 +41,5 @@ library
bytestring >= 0.10.6.0
ghc-options: -Wall
exposed-modules: Data.Compact
Data.Compact.Internal
Data.Compact.Serialized
exposed-modules: GHC.Compact
GHC.Compact.Serialized
......@@ -3,7 +3,7 @@ module Main where
import Control.Exception
import System.Mem
import Data.Compact
import GHC.Compact
assertFail :: String -> IO ()
assertFail msg = throwIO $ AssertionFailed msg
......
......@@ -3,8 +3,7 @@ module Main where
import Control.Exception
import System.Mem
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
assertFail :: String -> IO ()
assertFail msg = throwIO $ AssertionFailed msg
......
import Control.Exception
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
import qualified Data.Map as Map
import Data.Time.Clock
import Text.Printf
......
import qualified Data.ByteString.Char8 as B
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
import qualified Data.Map as Map
main = do
......
import Control.Exception
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
import qualified Data.Map as Map
import System.Exit
......
import Control.Exception
import Data.Compact
import GHC.Compact
data HiddenFunction = HiddenFunction (Int -> Int)
......
import Control.Monad
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
import qualified Data.Map as Map
main = do
......
......@@ -9,8 +9,7 @@ import Data.Array
import Data.Array.ST
import qualified Data.Array.Unboxed as U
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
assertFail :: String -> IO ()
assertFail msg = throwIO $ AssertionFailed msg
......
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
import qualified Data.Map as Map
main = do
......
......@@ -4,8 +4,7 @@ import Control.Exception
import System.Mem
import Text.Show
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
assertFail :: String -> IO ()
assertFail msg = throwIO $ AssertionFailed msg
......
import Control.Concurrent
import Control.Exception
import Data.Compact
import GHC.Compact
data HiddenMVar = HiddenMVar (MVar ())
......
import Control.Exception
import qualified Data.ByteString.Char8 as B
import Data.Compact
import GHC.Compact
main = compact (B.pack ['a'..'c'])
......@@ -8,9 +8,8 @@ import Data.IORef
import Data.ByteString (ByteString, packCStringLen)
import Foreign.Ptr
import Data.Compact
import Data.Compact.Internal
import Data.Compact.Serialized
import GHC.Compact
import GHC.Compact.Serialized
assertFail :: String -> IO ()
assertFail msg = throwIO $ AssertionFailed msg
......
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
import qualified Data.Map as Map
main = do
......
......@@ -3,7 +3,7 @@ module Main where
import Control.Exception
import System.Mem
import Data.Compact
import GHC.Compact
assertFail :: String -> IO ()
assertFail msg = throwIO $ AssertionFailed msg
......
......@@ -9,8 +9,7 @@ import Data.Array
import Data.Array.ST
import qualified Data.Array.Unboxed as U
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
assertFail :: String -> IO ()
assertFail msg = throwIO $ AssertionFailed msg
......
import Control.Concurrent
import Control.Monad
import Data.Compact
import Data.Compact.Internal
import GHC.Compact
import qualified Data.Map as Map
import Data.Maybe
import System.Environment
......
......@@ -45,7 +45,7 @@ libraries/array - - -
libraries/binary - - https://github.com/kolmodin/binary.git
libraries/bytestring - - https://github.com/haskell/bytestring.git
libraries/Cabal - - https://github.com/haskell/cabal.git
libraries/compact - - -
libraries/ghc-compact - - -
libraries/containers - - https://github.com/haskell/containers.git
libraries/deepseq - - ssh://git@github.com/haskell/deepseq.git
libraries/directory - - ssh://git@github.com/haskell/directory.git
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment