Data.Atom

hxt-9.3.1.22: A collection of tools for processing XML with Haskell.

Copyright | Copyright (C) 2008 Uwe Schmidt
License | MIT
Maintainer | Uwe Schmidt (uwe\@fh-wedel.de)
Stability | experimental
Portability | non-portable
Safe Haskell | None
Language | Haskell2010

Data.Atom

Contents

- Atom objects

Description

Unique Atoms generated from Strings and managed as flyweights

Data.Atom can be used for caching and storage optimization of frequently used strings. An `Atom` is constructed from a `String`. For two equal strings the identical atom is returned.

This module can be used for optimizing memory usage when working with strings or names. Many applications use data types like `Map String SomeAttribute` where a rather fixed set of keys is used. Especially XML applications often work with a limited set of element and attribute names. For these applications it becomes more memory efficient when working with types like `Map Atom SomeAttribute` and convert the keys into atoms before operating on such a map.

Internally this module manages a map of atoms. The atoms are internally represented by `ByteString`s. When creating a new atom from a string, the string is first converted into an UTF8 `Word8` sequence, which is packed into a `ByteString`. This `ByteString` is looked up in the table of atoms. If it is already there, the value in the map is used as atom, else the new `ByteString` is inserted into the map.

Of course the implementation of this name cache uses `unsavePerformIO`. The global cache is managed by ue of an `IORef` and atomicModifyIORef.

The following laws hold for atoms

    s  ==       t => newAtom s  ==       newAtom t
    s `compare` t => newAtom s `compare` newAtom t
    show . newAtom == id

Equality test for `Atom`s runs in O(1), it is just a pointer comparison. The `Ord` comparisons have the same runtime like the `ByteString` comparisons. Internally there is an UTF8 comparison, but UTF8 encoding preserves the total order.

Warning: The internal cache never shrinks during execution. So using it in a undisciplined way can lead to memory leaks.

Synopsis

- data Atom
- newAtom :: String -> Atom
- share :: String -> String

# Atom objects

data Atom #

#### Instances

Instances details

NFData Atom # |
Instance details Defined in Data.Atom Methods rnf :: Atom -> () #
Read Atom # |
Instance details Defined in Data.Atom Methods readsPrec :: Int -> ReadS Atom # readList :: ReadS [Atom] # readPrec :: ReadPrec Atom # readListPrec :: ReadPrec [Atom] #
Show Atom # |
Instance details Defined in Data.Atom Methods showsPrec :: Int -> Atom -> ShowS # show :: Atom -> String # showList :: [Atom] -> ShowS #
Eq Atom # |
Instance details Defined in Data.Atom Methods (==) :: Atom -> Atom -> Bool # (/=) :: Atom -> Atom -> Bool #
Ord Atom # |
Instance details Defined in Data.Atom Methods compare :: Atom -> Atom -> Ordering # (<) :: Atom -> Atom -> Bool # (<=) :: Atom -> Atom -> Bool # (>) :: Atom -> Atom -> Bool # (>=) :: Atom -> Atom -> Bool # max :: Atom -> Atom -> Atom # min :: Atom -> Atom -> Atom #

newAtom :: String -> Atom #

creation of an `Atom` from a `String`

share :: String -> String #

Insert a `String` into the atom cache and convert the atom back into a `String`.

locically `share == id` holds, but internally equal strings share the same memory.