-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | In memory storage of deeply evaluated data structure
°5u
°5uThis package provides minimal functionality for working with "compact
°5uregions", which hold a fully evaluated Haskell object graph. These
°5uregions maintain the invariant that no pointers live inside the struct
°5uthat point outside it, which ensures efficient garbage collection
°5uwithout ever reading the structure contents (effectively, it works as
°5ua manually managed "oldest generation" which is never freed until the
°5uwhole is released). Internally, the struct is stored a single
°5ucontiguous block of memory, which allows efficient serialization and
°5udeserialization of structs for distributed computing.
@package ghc-compact
@version 0.1.0.0


-- | This module provides a data structure, called a <a>Compact</a>, for
°5uholding immutable, fully evaluated data in a consecutive block of
°5umemory. Compact regions are good for two things:
°5u
°5u<ol>
°5u<li>Data in a compact region is not traversed during GC; any incoming
°5upointer to a compact region keeps the entire region live. Thus, if you
°5uput a long-lived data structure in a compact region, you may save a
°5ulot of cycles during major collections, since you will no longer be
°5u(uselessly) retraversing this data structure.</li>
°5u<li>Because the data is stored contiguously, you can easily dump the
°5umemory to disk and/or send it over the network. For applications that
°5uare not bandwidth bound (GHC's heap representation can be as much of a
°5ux4 expansion over a binary serialization), this can lead to
°5usubstantial speedups.</li>
°5u</ol>
°5u
°5uFor example, suppose you have a function <tt>loadBigStruct :: IO
°5uBigStruct</tt>, which loads a large data structure from the file
°5usystem. You can "compact" the structure with the following code:
°5u
°5u<pre>
°5udo r &lt;- <a>compact</a> =&lt;&lt; loadBigStruct
°5u   let x = <a>getCompact</a> r :: BigStruct
°5u   -- Do things with x
°5u</pre>
°5u
°5uNote that <a>compact</a> will not preserve internal sharing; use
°5u<a>compactWithSharing</a> (which is 10x slower) if you have cycles
°5uand/or must preserve sharing. The <a>Compact</a> pointer <tt>r</tt>
°5ucan be used to add more data to a compact region; see
°5u<a>compactAdd</a> or <a>compactAddWithSharing</a>.
°5u
°5uThe implementation of compact regions is described by:
°5u
°5u<ul>
°5u<li>Edward Z. Yang, Giovanni Campagna, Ömer Ağacan, Ahmed El-Hassany,
°5uAbhishek Kulkarni, Ryan Newton. "/Efficient communication and
°5uCollection with Compact Normal Forms/". In Proceedings of the 20th ACM
°5uSIGPLAN International Conference on Functional Programming. September
°5u2015. <a>http://ezyang.com/compact.html</a></li>
°5u</ul>
°5u
°5uThis library is supported by GHC 8.2 and later.
module GHC.Compact

-- | A <a>Compact</a> contains fully evaluated, pure, immutable data.
°5u
°5u<a>Compact</a> serves two purposes:
°5u
°5u<ul>
°5u<li>Data stored in a <a>Compact</a> has no garbage collection
°5uoverhead. The garbage collector considers the whole <a>Compact</a> to
°5ube alive if there is a reference to any object within it.</li>
°5u<li>A <a>Compact</a> can be serialized, stored, and deserialized
°5uagain. The serialized data can only be deserialized by the exact
°5ubinary that created it, but it can be stored indefinitely before
°5udeserialization.</li>
°5u</ul>
°5u
°5uCompacts are self-contained, so compacting data involves copying it;
°5uif you have data that lives in two <a>Compact</a>s, each will have a
°5useparate copy of the data.
°5u
°5uThe cost of compaction is similar to the cost of GC for the same data,
°5ubut it is performed only once. However, because "GHC.Compact.compact"
°5udoes not stop-the-world, retaining internal sharing during the
°5ucompaction process is very costly. The user can choose whether to
°5u<a>compact</a> or <a>compactWithSharing</a>.
°5u
°5uWhen you have a <tt><a>Compact</a> a</tt>, you can get a pointer to
°5uthe actual object in the region using "GHC.Compact.getCompact". The
°5u<a>Compact</a> type serves as handle on the region itself; you can use
°5uthis handle to add data to a specific <a>Compact</a> with
°5u<a>compactAdd</a> or <a>compactAddWithSharing</a> (giving you a new
°5uhandle which corresponds to the same compact region, but points to the
°5unewly added object in the region). At the moment, due to technical
°5ureasons, it's not possible to get the <tt><a>Compact</a> a</tt> if you
°5uonly have an <tt>a</tt>, so make sure you hold on to the handle as
°5unecessary.
°5u
°5uData in a compact doesn't ever move, so compacting data is also a way
°5uto pin arbitrary data structures in memory.
°5u
°5uThere are some limitations on what can be compacted:
°5u
°5u<ul>
°5u<li>Functions. Compaction only applies to data.</li>
°5u<li>Pinned <a>ByteArray#</a> objects cannot be compacted. This is for
°5ua good reason: the memory is pinned so that it can be referenced by
°5uaddress (the address might be stored in a C data structure, for
°5uexample), so we can't make a copy of it to store in the
°5u<a>Compact</a>.</li>
°5u<li>Objects with mutable pointer fields (e.g. <a>IORef</a>,
°5u<a>MutableArray</a>) also cannot be compacted, because subsequent
°5umutation would destroy the property that a compact is
°5uself-contained.</li>
°5u</ul>
°5u
°5uIf compaction encounters any of the above, a <tt>CompactionFailed</tt>
°5uexception will be thrown by the compaction operation.
data Compact a
Compact :: Compact# -> a -> (MVar ()) -> Compact a

-- | Compact a value. <i>O(size of unshared data)</i>
°5u
°5uIf the structure contains any internal sharing, the shared data will
°5ube duplicated during the compaction process. This will not terminate
°5uif the structure contains cycles (use <a>compactWithSharing</a>
°5uinstead).
°5u
°5uThe object in question must not contain any functions or data with
°5umutable pointers; if it does, <a>compact</a> will raise an exception.
°5uIn the future, we may add a type class which will help statically
°5ucheck if this is the case or not.
compact :: a -> IO (Compact a)

-- | Compact a value, retaining any internal sharing and cycles. <i>O(size
°5uof data)</i>
°5u
°5uThis is typically about 10x slower than <a>compact</a>, because it
°5uworks by maintaining a hash table mapping uncompacted objects to
°5ucompacted objects.
°5u
°5uThe object in question must not contain any functions or data with
°5umutable pointers; if it does, <a>compact</a> will raise an exception.
°5uIn the future, we may add a type class which will help statically
°5ucheck if this is the case or not.
compactWithSharing :: a -> IO (Compact a)

-- | Add a value to an existing <a>Compact</a>. This will help you avoid
°5ucopying when the value contains pointers into the compact region, but
°5uremember that after compaction this value will only be deallocated
°5uwith the entire compact region.
°5u
°5uBehaves exactly like <a>compact</a> with respect to sharing and what
°5udata it accepts.
compactAdd :: Compact b -> a -> IO (Compact a)

-- | Add a value to an existing <a>Compact</a>, like <a>compactAdd</a>, but
°5ubehaving exactly like <a>compactWithSharing</a> with respect to
°5usharing and what data it accepts.
compactAddWithSharing :: Compact b -> a -> IO (Compact a)

-- | Retrieve a direct pointer to the value pointed at by a <a>Compact</a>
°5ureference. If you have used <a>compactAdd</a>, there may be multiple
°5u<a>Compact</a> references into the same compact region. Upholds the
°5uproperty:
°5u
°5u<pre>
°5uinCompact c (getCompact c) == True
°5u</pre>
getCompact :: Compact a -> a

-- | Check if the second argument is inside the passed <a>Compact</a>.
inCompact :: Compact b -> a -> IO Bool

-- | Check if the argument is in any <a>Compact</a>. If true, the value in
°5uquestion is also fully evaluated, since any value in a compact region
°5umust be fully evaluated.
isCompact :: a -> IO Bool

-- | Returns the size in bytes of the compact region.
compactSize :: Compact a -> IO Word

-- | <ul>
°5u<li>Experimental.* This function doesn't actually resize a compact
°5uregion; rather, it changes the default block size which we allocate
°5uwhen the current block runs out of space, and also appends a block to
°5uthe compact region.</li>
°5u</ul>
compactResize :: Compact a -> Word -> IO ()

-- | Make a new <a>Compact</a> object, given a pointer to the true
°5uunderlying region. You must uphold the invariant that <tt>a</tt> lives
°5uin the compact region.
mkCompact :: Compact# -> a -> State# RealWorld -> (# State# RealWorld, Compact a #)

-- | Transfer <tt>a</tt> into a new compact region, with a preallocated
°5usize, possibly preserving sharing or not. If you know how big the data
°5ustructure in question is, you can save time by picking an appropriate
°5ublock size for the compact region.
compactSized :: Int -> Bool -> a -> IO (Compact a)


-- | This module contains support for serializing a Compact for network
°5utransmission and on-disk storage.
°5u
°5u<i>Since: 1.0.0</i>
module GHC.Compact.Serialized

-- | A serialized version of the <a>Compact</a> metadata (each block with
°5uaddress and size and the address of the root). This structure is meant
°5uto be sent alongside the actual <a>Compact</a> data. It can be sent
°5uout of band in advance if the data is to be sent over RDMA (which
°5urequires both sender and receiver to have pinned buffers).
data SerializedCompact a
SerializedCompact :: [(Ptr a, Word)] -> Ptr a -> SerializedCompact a
[serializedCompactBlockList] :: SerializedCompact a -> [(Ptr a, Word)]
[serializedCompactRoot] :: SerializedCompact a -> Ptr a

-- | Serialize the <a>Compact</a>, and call the provided function with with
°5uthe <a>Compact</a> serialized representation. It is not safe to return
°5uthe pointer from the action and use it after the action completes: all
°5uuses must be inside this bracket, since we cannot guarantee that the
°5ucompact region will stay live from the <a>Ptr</a> object. For example,
°5uit would be unsound to use <tt>unsafeInterleaveIO</tt> to lazily
°5uconstruct a lazy bytestring from the <a>Ptr</a>.
withSerializedCompact :: Compact a -> (SerializedCompact a -> IO c) -> IO c

-- | Deserialize a <a>SerializedCompact</a> into a in-memory
°5u<a>Compact</a>. The provided function will be called with the address
°5uand size of each newly allocated block in succession, and should fill
°5uthe memory from the external source (eg. by reading from a socket or
°5ufrom disk) <a>importCompact</a> can return Nothing if the
°5u<a>Compact</a> was corrupt or it had pointers that could not be
°5uadjusted.
importCompact :: SerializedCompact a -> (Ptr b -> Word -> IO ()) -> IO (Maybe (Compact a))

-- | Convenience function for importing a compact region that is
°5urepresented by a list of strict <tt>ByteString</tt>s.
importCompactByteStrings :: SerializedCompact a -> [ByteString] -> IO (Maybe (Compact a))
