diff --git a/BerkeleyDBXML.cabal b/BerkeleyDBXML.cabal
--- a/BerkeleyDBXML.cabal
+++ b/BerkeleyDBXML.cabal
@@ -1,5 +1,5 @@
 name: BerkeleyDBXML
-version: 0.2
+version: 0.3
 license: BSD3
 license-file: LICENSE
 cabal-version: >= 1.4
@@ -8,7 +8,23 @@
 maintainer: http://blacksapphire.com/antispam/
 stability: alpha
 synopsis: Berkeley DB and Berkeley DB XML binding
-description: Berkeley DB and Berkeley DB XML binding
+description:
+    Berkeley DB XML is a powerful, fully transactional, XML-based database that uses
+    XQuery as its query language.  Berkeley DB XML is built on top of Berkeley DB.
+    It is NOT an SQL database.
+    .
+    This package provides a 70% complete Haskell binding for Berkeley DB and Berkeley
+    DB XML.  It is also possible to compile for Berkeley DB only.
+    .
+    Berkeley DB XML home page:
+    <http://www.oracle.com/database/berkeley-db/xml/index.html>
+    .
+    Haskell binding tutorial:
+    <http://www.haskell.org/haskellwiki/BerkeleyDBXML>
+    .
+    DARCS repository:
+    <http://blacksapphire.com/BerkeleyDBXML/>
+
 category: Database
 build-type: Simple
 homepage: http://www.haskell.org/haskellwiki/BerkeleyDBXML
diff --git a/Database/Berkeley/Db.hs b/Database/Berkeley/Db.hs
--- a/Database/Berkeley/Db.hs
+++ b/Database/Berkeley/Db.hs
@@ -1,50 +1,58 @@
 {-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}
 {-# CFILES Database/Berkeley/db_helper.cpp #-}
 
+-- | All IO monad functions can throw exceptions.  Use getDbError to fetch the
+-- error code.
+
 module Database.Berkeley.Db (
-        DbEnv,
+        -- * General
+        DbFlag(..),
         DbError(..),
         getDbError,
+        -- * DbEnv
+        DbEnv,
+        dbEnv_close,
         dbEnv_create,
+        dbEnv_get_cache_size,
+        dbEnv_get_lg_regionmax,
         dbEnv_get_lk_max_lockers,
-        dbEnv_set_lk_max_lockers,
         dbEnv_get_lk_max_locks,
-        dbEnv_set_lk_max_locks,
         dbEnv_get_lk_max_objects,
-        dbEnv_set_lk_max_objects,
         dbEnv_get_tx_max,
-        dbEnv_set_tx_max,
-        dbEnv_get_cache_size,
+        DbLocker,
+        DbLockMode(..),
+        dbEnv_lock_get,
+        dbEnv_lock_put,
+        dbEnv_open,
         dbEnv_set_cache_size,
-        dbEnv_get_lg_regionmax,
         dbEnv_set_lg_regionmax,
-        DbFlag(..),
-        dbEnv_open,
-        dbToNum,  -- ^ Private to DbXml
-        dbOrFlags,  -- ^ Private to DbXml
-        Db,
-        db_create,
-        db_set_pagesize,
-        DbType(..),
-        DbTxn,
-        DbTxn_struct,  -- ^ Private to DbXml
-        db_open,
+        DbLockFlag(..),
+        dbEnv_set_lk_detect,
+        dbEnv_set_lk_max_lockers,
+        dbEnv_set_lk_max_locks,
+        dbEnv_set_lk_max_objects,
+        dbEnv_set_tx_max,
         dbEnv_txn_begin,
         dbEnv_txn_checkpoint,
+        -- * DbTxn
+        DbTxn,
         dbTxn_abort,
         dbTxn_commit,
-        DbLocker,
         dbTxn_id,
-        DbLockMode(..),
-        dbEnv_lock_get,
-        dbEnv_lock_put,
+        -- * Db
+        Db,
+        db_close,
+        db_create,
+        db_del,
         db_get,
+        DbType(..),
+        db_open,
         db_put,
-        db_del,
-        db_close,
-        dbEnv_close,
-        DbLockFlag(..),
-        dbEnv_set_lk_detect
+        db_set_pagesize,
+        -- * Private
+        dbOrFlags,     -- Private to DbXml
+        dbToNum,       -- Private to DbXml
+        DbTxn_struct   -- Private to DbXml
     ) where
 
 import Foreign.C
@@ -133,6 +141,8 @@
 dbErrFromNum 0        = Nothing
 dbErrFromNum n        = Just (SYSTEM_ERROR n)
 
+-- | Helper specific to Haskell binding: Fetches a DbError value out of a Haskell
+-- IOError, so the caller can catch an exception and check the error code.
 getDbError :: IOError -> Maybe DbError
 getDbError ioError =
     if isUserError ioError
diff --git a/Database/Berkeley/DbXml.hs b/Database/Berkeley/DbXml.hs
--- a/Database/Berkeley/DbXml.hs
+++ b/Database/Berkeley/DbXml.hs
@@ -1,53 +1,67 @@
 {-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls, TypeSynonymInstances #-}
 {-# CFILES Database/Berkeley/dbxml_helper.cpp #-}
 
+-- | All IO monad functions can throw exceptions.  Use getDbXmlError to fetch the
+-- error code.
+
 module Database.Berkeley.DbXml (
+        -- * General
+        DbXmlFlag(..),
         ExceptionCode(..),
+        XmlResults,
+        XmlResultsReturnable,
         getDbXmlError,
-        DbXmlFlag(..),
-        XmlManager,
-        xmlManager_create,
+        -- * XmlContainer
         XmlContainer,
-        ContainerType(..),
-        xmlManager_openContainer,
-        XmlTransaction,
-        xmlManager_createTransaction,
-        xmlManager_createTransaction_DbTxn,
-        xmlTransaction_commit,
-        xmlTransaction_abort,
-        XmlDocument,
+        xmlContainer_close,
+        xmlContainer_deleteDocument,
         xmlContainer_getDocument,
         xmlContainer_getName,
+        xmlContainer_putDocument,
+        xmlContainer_updateDocument,
+        -- * XmlDocument
+        XmlDocument,
         xmlDocument_getContent,
-        XmlQueryContext,
+        xmlDocument_getName,
+        xmlDocument_setContent,
+        xmlDocument_setName,
+        -- * XmlManager
+        XmlManager,
+        xmlManager_close,
+        xmlManager_create,
+        xmlManager_createDocument,
         ReturnType(..),
         EvaluationType(..),
         xmlManager_createQueryContext,
+        xmlManager_createTransaction,
+        xmlManager_createTransaction_DbTxn,
+        xmlManager_createUpdateContext,
+        ContainerType(..),
+        xmlManager_openContainer,
+        xmlManager_prepare,
         xmlManager_query,
-        XmlResults,
-        XmlResultsReturnable,
+        -- * XmlQueryContext
+        XmlQueryContext,
+        xmlQueryContext_setDefaultCollection,
+        xmlQueryContext_setVariableValue,
+        -- * XmlQueryExpression
+        XmlQueryExpression,
+        xmlQueryExpression_execute,
+        -- * XmlResults
         xmlResults_hasNext,
         xmlResults_next,
-        xmlManager_prepare,
-        xmlQueryContext_setDefaultCollection,
+        -- * XmlTransaction
+        XmlTransaction,
+        xmlTransaction_abort,
+        xmlTransaction_commit,
+        -- * XmlValue
         XmlValue,
-        xmlNone,
-        xmlString,
         xmlBool,
         xmlDouble,
+        xmlNone,
+        xmlString,
         xmlValue_asString,
-        xmlValue_asString8Bit,
-        xmlQueryContext_setVariableValue,
-        XmlQueryExpression,
-        xmlQueryExpression_execute,
-        xmlManager_createDocument,
-        xmlDocument_getName,
-        xmlDocument_setName,
-        xmlManager_createUpdateContext,
-        xmlDocument_setContent,
-        xmlContainer_updateDocument,
-        xmlContainer_putDocument,
-        xmlContainer_deleteDocument
+        xmlValue_asString8Bit
     ) where
 
 import Foreign.C
@@ -149,6 +163,8 @@
 dbxmlErrFromNum 22 = Just OPERATION_INTERRUPTED
 dbxmlErrFromNum _  = Nothing
 
+-- | Helper specific to Haskell binding: Fetches a Berkeley DB XML ExceptionCode
+-- value out of a Haskell IOError so the caller can check the return code.
 getDbXmlError :: IOError -> Maybe ExceptionCode
 getDbXmlError ioError =
     if isUserError ioError
@@ -166,7 +182,7 @@
     DBXML_ALLOW_EXTERNAL_ACCESS |    -- ^ allow FS and net access
     DBXML_ALLOW_AUTO_OPEN       |    -- ^ auto-open in queries
 
-    -- | Flags used for container create/open
+    -- Flags used for container create/open
     DBXML_ALLOW_VALIDATION      |    -- ^ validate if specified
     DBXML_TRANSACTIONAL         |    -- ^ transactional container
     DBXML_CHKSUM                |    -- ^ use DB_CKSUM
@@ -176,8 +192,8 @@
     DBXML_STATISTICS            |    -- ^ Store statistics about the data
     DBXML_NO_STATISTICS         |    -- ^ Do not store statistics about the data
 
-    -- | these next three are only used by XmlContainer::lookupIndex, and can
-    -- | safely re-use the preceding enumeration values.
+    -- these next three are only used by XmlContainer::lookupIndex, and can
+    -- safely re-use the preceding enumeration values.
     DBXML_REVERSE_ORDER         |    -- ^ return in reverse sort
     DBXML_INDEX_VALUES          |    -- ^ return values also
     DBXML_CACHE_DOCUMENTS       |    -- ^ ensure that two index entries that refer to the same document return the exact same XmlDocument object
@@ -185,9 +201,9 @@
     DBXML_LAZY_DOCS             |    -- ^ lazily materialize docs
     DBXML_DOCUMENT_PROJECTION   |    -- ^Use the document projection optimisation
     DBXML_NO_AUTO_COMMIT        |    -- ^ Do not auto transact the operation
-    -- | below used for putDocument, and query operations (reuses enum)
+    -- below used for putDocument, and query operations (reuses enum)
     DBXML_WELL_FORMED_ONLY      |    -- ^ well-formed parser only
-    -- | only used in putDocument, safe to reuse enum above
+    -- only used in putDocument, safe to reuse enum above
     DBXML_GEN_NAME              |    -- ^ generate name in putDoc
     DB_FLAG DbFlag                   -- ^ For wrapping a Berkeley DB flag
 
@@ -790,4 +806,21 @@
     if ret /= 0
         then throw "xmlContainer_deleteDocument" ret ""
         else return ()
+
+foreign import ccall unsafe "dbxml_helper.h _xmlContainer_close" _xmlContainer_close
+    :: Ptr XmlContainer_struct -> IO ()
+
+-- | Closes a container. Equivalent to destructing the XmlContainer object in C++.        
+xmlContainer_close :: XmlContainer -> IO ()
+xmlContainer_close cont =
+    withForeignPtr cont$ \cont_ ->
+        _xmlContainer_close cont_
+
+foreign import ccall unsafe "dbxml_helper.h _xmlManager_close" _xmlManager_close
+    :: Ptr XmlManager_struct -> IO ()
+
+-- | Closes an XmlManager. Equivalent to destructing the XmlManager object in C++.        
+xmlManager_close :: XmlManager -> IO ()
+xmlManager_close mgr =
+    _xmlManager_close mgr
 
diff --git a/Database/Berkeley/dbxml_helper.cpp b/Database/Berkeley/dbxml_helper.cpp
--- a/Database/Berkeley/dbxml_helper.cpp
+++ b/Database/Berkeley/dbxml_helper.cpp
@@ -8,7 +8,39 @@
 using namespace DbXml;
 using namespace std;
 
+XmlManagerInfo::XmlManagerInfo()
+{
+    pthread_mutexattr_t attr;
+    pthread_mutexattr_init(&attr);
+    pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+    pthread_mutex_init(&mutex, &attr);
+}
 
+XmlManagerInfo::~XmlManagerInfo()
+{
+    while (queryExpressions.begin() != queryExpressions.end())
+        delete *queryExpressions.begin();
+}
+
+XmlQueryExpressionInfo::XmlQueryExpressionInfo(
+    DbXml::XmlQueryExpression qe,
+    XmlManagerInfo* mi)
+    : qe(qe), mi(mi)
+{
+    pthread_mutex_lock(&mi->mutex);
+    mi->queryExpressions.insert(this);
+    pthread_mutex_unlock(&mi->mutex);
+}
+
+XmlQueryExpressionInfo::~XmlQueryExpressionInfo()
+{
+    pthread_mutex_lock(&mi->mutex);
+    std::set<XmlQueryExpressionInfo*>::iterator it = mi->queryExpressions.find(this);
+    if (it != mi->queryExpressions.end())
+        mi->queryExpressions.erase(it);
+    pthread_mutex_unlock(&mi->mutex);
+}
+
 static int asInt(XmlException& exc)
 {
     int dbE = exc.getDbErrno();
@@ -17,26 +49,34 @@
     return (exc.getExceptionCode() + 1) * 100000 + dbE;
 }
 
-int _xmlManager(DbEnv* dbenv, u_int32_t flags, DbXml::XmlManager** mgr)
+int _xmlManager(DbEnv* dbenv, u_int32_t flags, XmlManagerInfo** mgr)
 {
+    *mgr = new XmlManagerInfo;
     try {
-        *mgr = new XmlManager(dbenv, flags);
+        (*mgr)->mgr = XmlManager(dbenv, flags);
         return 0;
     }
     catch (XmlException& exc) {
+        delete *mgr;
         *mgr = NULL;
         return asInt(exc);
     }
 }
 
-int _xmlManager_openContainer(DbXml::XmlManager* mgr, const char* name, u_int32_t flags,
-    int cType, int mode, DbXml::XmlContainer** container)
+void _xmlManager_close(XmlManagerInfo* mgr)
 {
+    delete mgr;
+}
+
+int _xmlManager_openContainer(XmlManagerInfo* mgr, const char* name, u_int32_t flags,
+    int cType, int mode, DbXml::XmlContainer*** container)
+{
     try {
-        DbXml::XmlContainer c = mgr->openContainer(name, flags,
+        DbXml::XmlContainer c = mgr->mgr.openContainer(name, flags,
             cType == 0 ? XmlContainer::NodeContainer : XmlContainer::WholedocContainer,
             mode);
-        *container = new DbXml::XmlContainer(c);
+        *container = new DbXml::XmlContainer*;
+        **container = new DbXml::XmlContainer(c);
         return 0;
     }
     catch (XmlException& exc) {
@@ -45,15 +85,22 @@
     }
 }
 
-void _xmlContainer_delete(DbXml::XmlContainer* cont)
+void _xmlContainer_delete(DbXml::XmlContainer** cont)
 {
+    delete *cont;
     delete cont;
 }
 
-int _xmlManager_createTransaction(DbXml::XmlManager* mgr, u_int32_t flags, DbXml::XmlTransaction** trans)
+void _xmlContainer_close(DbXml::XmlContainer** cont)
 {
+    delete *cont;
+    *cont = NULL;
+}
+
+int _xmlManager_createTransaction(XmlManagerInfo* mgr, u_int32_t flags, DbXml::XmlTransaction** trans)
+{
     try {
-        XmlTransaction t = mgr->createTransaction(flags);
+        XmlTransaction t = mgr->mgr.createTransaction(flags);
         *trans = new XmlTransaction(t);
         return 0;
     }
@@ -63,10 +110,10 @@
     }
 }
 
-int _xmlManager_createTransaction_DbTxn(DbXml::XmlManager* mgr, DbTxn* dbtxn, DbXml::XmlTransaction** trans)
+int _xmlManager_createTransaction_DbTxn(XmlManagerInfo* mgr, DbTxn* dbtxn, DbXml::XmlTransaction** trans)
 {
     try {
-        XmlTransaction t = mgr->createTransaction(dbtxn);
+        XmlTransaction t = mgr->mgr.createTransaction(dbtxn);
         *trans = new XmlTransaction(t);
         return 0;
     }
@@ -103,15 +150,15 @@
     }
 }
 
-int _xmlContainer_getDocument(DbXml::XmlContainer* cont, DbXml::XmlTransaction* trans,
+int _xmlContainer_getDocument(DbXml::XmlContainer** cont, DbXml::XmlTransaction* trans,
     const char* key, u_int32_t flags, DbXml::XmlDocument** doc)
 {
     try {
         XmlDocument d;
         if (trans != NULL)
-            d = cont->getDocument(*trans, key, flags);
+            d = (*cont)->getDocument(*trans, key, flags);
         else
-            d = cont->getDocument(key, flags);
+            d = (*cont)->getDocument(key, flags);
         *doc = new XmlDocument(d);
         return 0;
     }
@@ -121,9 +168,9 @@
     }
 }
 
-char* _xmlContainer_getName(DbXml::XmlContainer* cont)
+char* _xmlContainer_getName(DbXml::XmlContainer** cont)
 {
-    string s = cont->getName();
+    string s = (*cont)->getName();
     char* str = new char[s.length()+1];
     strcpy(str, s.c_str());
     return str;
@@ -149,10 +196,10 @@
     return 0;
 }
 
-int _xmlManager_createQueryContext(DbXml::XmlManager* mgr, int rt, int ev, DbXml::XmlQueryContext** ctx)
+int _xmlManager_createQueryContext(XmlManagerInfo* mgr, int rt, int ev, DbXml::XmlQueryContext** ctx)
 {
     try {
-        XmlQueryContext c = mgr->createQueryContext(
+        XmlQueryContext c = mgr->mgr.createQueryContext(
             XmlQueryContext::LiveValues,
             ev == 0 ? XmlQueryContext::Eager : XmlQueryContext::Lazy);
         *ctx = new XmlQueryContext(c);
@@ -219,15 +266,15 @@
     }
 }
 
-int _xmlManager_query(DbXml::XmlManager* mgr, DbXml::XmlTransaction* trans,
+int _xmlManager_query(XmlManagerInfo* mgr, DbXml::XmlTransaction* trans,
     const char* query, DbXml::XmlQueryContext* ctx, u_int32_t flags, DbXml::XmlResults** res)
 {
     try {
         XmlResults r;
         if (trans != NULL)
-            r = mgr->query(*trans, query, *ctx, flags);
+            r = mgr->mgr.query(*trans, query, *ctx, flags);
         else
-            r = mgr->query(query, *ctx, flags);
+            r = mgr->mgr.query(query, *ctx, flags);
         *res = new XmlResults(r);
         return 0;
     }
@@ -237,21 +284,21 @@
     }
 }
 
-void _xmlQueryExpression_delete(DbXml::XmlQueryExpression* exp)
+void _xmlQueryExpression_delete(XmlQueryExpressionInfo* exp)
 {
     delete exp;
 }
 
-int _xmlManager_prepare(DbXml::XmlManager* mgr, DbXml::XmlTransaction* trans,
-    const char* query, DbXml::XmlQueryContext* ctx, DbXml::XmlQueryExpression** exp)
+int _xmlManager_prepare(XmlManagerInfo* mgr, DbXml::XmlTransaction* trans,
+    const char* query, DbXml::XmlQueryContext* ctx, XmlQueryExpressionInfo** exp)
 {
     try {
         XmlQueryExpression e;
         if (trans != NULL)
-            e = mgr->prepare(*trans, query, *ctx);
+            e = mgr->mgr.prepare(*trans, query, *ctx);
         else
-            e = mgr->prepare(query, *ctx);
-        *exp = new XmlQueryExpression(e);
+            e = mgr->mgr.prepare(query, *ctx);
+        *exp = new XmlQueryExpressionInfo(e, mgr);
         return 0;
     }
     catch (XmlException& exc) {
@@ -322,21 +369,21 @@
     return 0;
 }
 
-int _xmlQueryExpression_execute(DbXml::XmlQueryExpression* exp, DbXml::XmlTransaction* trans,
+int _xmlQueryExpression_execute(XmlQueryExpressionInfo* exp, DbXml::XmlTransaction* trans,
     DbXml::XmlValue* contextItem, DbXml::XmlQueryContext* qctx, u_int32_t flags, DbXml::XmlResults** res)
 {
     try {
         XmlResults r;
         if (trans != NULL && contextItem != NULL)
-            r = exp->execute(*trans, *contextItem, *qctx, flags);
+            r = exp->qe.execute(*trans, *contextItem, *qctx, flags);
         else
         if (trans != NULL && contextItem == NULL)
-            r = exp->execute(*trans, *qctx, flags);
+            r = exp->qe.execute(*trans, *qctx, flags);
         else
         if (trans == NULL && contextItem != NULL)
-            r = exp->execute(*contextItem, *qctx, flags);
+            r = exp->qe.execute(*contextItem, *qctx, flags);
         else
-            r = exp->execute(*qctx, flags);
+            r = exp->qe.execute(*qctx, flags);
         *res = new XmlResults(r);
         return 0;
     }
@@ -346,10 +393,10 @@
     }
 }
 
-int _xmlManager_createDocument(DbXml::XmlManager* mgr, DbXml::XmlDocument** doc)
+int _xmlManager_createDocument(XmlManagerInfo* mgr, DbXml::XmlDocument** doc)
 {
     try {
-        XmlDocument d = mgr->createDocument();
+        XmlDocument d = mgr->mgr.createDocument();
         *doc = new XmlDocument(d);
         return 0;
     }
@@ -390,10 +437,10 @@
     delete ctx;
 }
 
-int _xmlManager_createUpdateContext(DbXml::XmlManager* mgr, DbXml::XmlUpdateContext** ctx)
+int _xmlManager_createUpdateContext(XmlManagerInfo* mgr, DbXml::XmlUpdateContext** ctx)
 {
     try {
-        XmlUpdateContext c = mgr->createUpdateContext();
+        XmlUpdateContext c = mgr->mgr.createUpdateContext();
         *ctx = new XmlUpdateContext(c);
         return 0;
     }
@@ -415,14 +462,14 @@
     }
 }
 
-int _xmlContainer_updateDocument(DbXml::XmlContainer* cont, DbXml::XmlTransaction* trans,
+int _xmlContainer_updateDocument(DbXml::XmlContainer** cont, DbXml::XmlTransaction* trans,
     DbXml::XmlDocument* doc, DbXml::XmlUpdateContext* uctx)
 {
     try {
         if (trans != NULL)
-            cont->updateDocument(*trans, *doc, *uctx);
+            (*cont)->updateDocument(*trans, *doc, *uctx);
         else
-            cont->updateDocument(*doc, *uctx);
+            (*cont)->updateDocument(*doc, *uctx);
         return 0;
     }
     catch (XmlException& exc) {
@@ -430,14 +477,14 @@
     }
 }
 
-int _xmlContainer_putDocument(DbXml::XmlContainer* cont, DbXml::XmlTransaction* trans,
+int _xmlContainer_putDocument(DbXml::XmlContainer** cont, DbXml::XmlTransaction* trans,
     DbXml::XmlDocument* doc, DbXml::XmlUpdateContext* uctx, u_int32_t flags)
 {
     try {
         if (trans != NULL)
-            cont->putDocument(*trans, *doc, *uctx, flags);
+            (*cont)->putDocument(*trans, *doc, *uctx, flags);
         else
-            cont->putDocument(*doc, *uctx, flags);
+            (*cont)->putDocument(*doc, *uctx, flags);
         return 0;
     }
     catch (XmlException& exc) {
@@ -445,14 +492,14 @@
     }
 }
 
-int _xmlContainer_deleteDocument(DbXml::XmlContainer* cont, DbXml::XmlTransaction* trans,
+int _xmlContainer_deleteDocument(DbXml::XmlContainer** cont, DbXml::XmlTransaction* trans,
     DbXml::XmlDocument* doc, DbXml::XmlUpdateContext* uctx)
 {
     try {
         if (trans != NULL)
-            cont->deleteDocument(*trans, *doc, *uctx);
+            (*cont)->deleteDocument(*trans, *doc, *uctx);
         else
-            cont->deleteDocument(*doc, *uctx);
+            (*cont)->deleteDocument(*doc, *uctx);
         return 0;
     }
     catch (XmlException& exc) {
diff --git a/Database/Berkeley/dbxml_helper.h b/Database/Berkeley/dbxml_helper.h
--- a/Database/Berkeley/dbxml_helper.h
+++ b/Database/Berkeley/dbxml_helper.h
@@ -2,33 +2,58 @@
 #define _DBXML_HELPER_H_
 
 #include <DbXml.hpp>
+#include <set>
+#include "pthread.h"
 
 extern "C" {
-    int _xmlManager(DbEnv* dbenv, u_int32_t flags, DbXml::XmlManager** mgr);
-    int _xmlManager_openContainer(DbXml::XmlManager* mgr, const char* name, u_int32_t flags,
-        int cType, int mode, DbXml::XmlContainer** container);
-    void _xmlContainer_delete(DbXml::XmlContainer* cont);
-    int _xmlManager_createTransaction(DbXml::XmlManager* mgr, u_int32_t flags, DbXml::XmlTransaction** trans);
-    int _xmlManager_createTransaction_DbTxn(DbXml::XmlManager* mgr, DbTxn* dbtxn, DbXml::XmlTransaction** trans);
+    struct XmlQueryExpressionInfo;
+
+    struct XmlManagerInfo {
+        XmlManagerInfo();
+        ~XmlManagerInfo();
+
+        pthread_mutex_t mutex;
+        DbXml::XmlManager mgr;
+        std::set<XmlQueryExpressionInfo*> queryExpressions;
+    };
+
+    struct XmlQueryExpressionInfo {
+        XmlQueryExpressionInfo(
+            DbXml::XmlQueryExpression qe,
+            XmlManagerInfo* mi);
+        ~XmlQueryExpressionInfo();
+
+        DbXml::XmlQueryExpression qe;
+        XmlManagerInfo* mi;
+    };
+
+    int _xmlManager(DbEnv* dbenv, u_int32_t flags, XmlManagerInfo** mgr);
+    void _xmlManager_close(XmlManagerInfo* mgr);
+    int _xmlManager_openContainer(XmlManagerInfo* mgr, const char* name, u_int32_t flags,
+        int cType, int mode, DbXml::XmlContainer*** container);
+    void _xmlContainer_delete(DbXml::XmlContainer** cont);
+    void _xmlContainer_close(DbXml::XmlContainer** cont);
+    int _xmlManager_createTransaction(XmlManagerInfo* mgr, u_int32_t flags, DbXml::XmlTransaction** trans);
+    int _xmlManager_createTransaction_DbTxn(XmlManagerInfo* mgr, DbTxn* dbtxn, DbXml::XmlTransaction** trans);
     void _xmlTransaction_delete(DbXml::XmlTransaction* trans);
     int _xmlTransaction_commit(DbXml::XmlTransaction* trans);
     int _xmlTransaction_abort(DbXml::XmlTransaction* trans);
-    int _xmlContainer_getDocument(DbXml::XmlContainer* cont, DbXml::XmlTransaction* trans,
+    int _xmlContainer_getDocument(DbXml::XmlContainer** cont, DbXml::XmlTransaction* trans,
         const char* key, u_int32_t flags, DbXml::XmlDocument** doc);
-    char* _xmlContainer_getName(DbXml::XmlContainer* cont);
+    char* _xmlContainer_getName(DbXml::XmlContainer** cont);
     void _xmlDocument_delete(DbXml::XmlDocument* doc);
     int _xmlDocument_getContent(DbXml::XmlDocument* doc, char** str);
-    int _xmlManager_createQueryContext(DbXml::XmlManager* mgr, int rt, int ev, DbXml::XmlQueryContext** ctx);
+    int _xmlManager_createQueryContext(XmlManagerInfo* mgr, int rt, int ev, DbXml::XmlQueryContext** ctx);
     void _xmlQueryContext_delete(DbXml::XmlQueryContext* ctx);
     void _xmlResults_delete(DbXml::XmlResults* res);
     int _xmlResults_hasNext(DbXml::XmlResults* res, int* answer);
     int _xmlResults_nextDocument(DbXml::XmlResults* res, DbXml::XmlDocument** doc);
     int _xmlResults_nextValue(DbXml::XmlResults* res, DbXml::XmlValue** val);
-    int _xmlManager_query(DbXml::XmlManager* mgr, DbXml::XmlTransaction* trans,
+    int _xmlManager_query(XmlManagerInfo* mgr, DbXml::XmlTransaction* trans,
         const char* query, DbXml::XmlQueryContext* ctx, u_int32_t flags, DbXml::XmlResults** res);
-    void _xmlQueryExpression_delete(DbXml::XmlQueryExpression* exp);
-    int _xmlManager_prepare(DbXml::XmlManager* mgr, DbXml::XmlTransaction* trans,
-        const char* query, DbXml::XmlQueryContext* ctx, DbXml::XmlQueryExpression** exp);
+    void _xmlQueryExpression_delete(XmlQueryExpressionInfo* exp);
+    int _xmlManager_prepare(XmlManagerInfo* mgr, DbXml::XmlTransaction* trans,
+        const char* query, DbXml::XmlQueryContext* ctx, XmlQueryExpressionInfo** exp);
     int _xmlQueryContext_setDefaultCollection(DbXml::XmlQueryContext* ctx, const char* coll);
     int _xmlQueryContext_setVariableValue(DbXml::XmlQueryContext* ctx, const char* name, DbXml::XmlValue* value);
     void _xmlValue_delete(DbXml::XmlValue* exp);
@@ -37,19 +62,19 @@
     DbXml::XmlValue* _xmlBool(int value);
     DbXml::XmlValue* _xmlDouble(double value);
     int _xmlValue_asString(DbXml::XmlValue* value, char** str);
-    int _xmlQueryExpression_execute(DbXml::XmlQueryExpression* exp, DbXml::XmlTransaction* trans,
+    int _xmlQueryExpression_execute(XmlQueryExpressionInfo* exp, DbXml::XmlTransaction* trans,
         DbXml::XmlValue* contextItem, DbXml::XmlQueryContext* qctx, u_int32_t flags, DbXml::XmlResults** res);
-    int _xmlManager_createDocument(DbXml::XmlManager* mgr, DbXml::XmlDocument** doc);
+    int _xmlManager_createDocument(XmlManagerInfo* mgr, DbXml::XmlDocument** doc);
     int _xmlDocument_getName(DbXml::XmlDocument* doc, char** name);
     int _xmlDocument_setName(DbXml::XmlDocument* doc, const char* name);
     void _xmlUpdateContext_delete(DbXml::XmlUpdateContext* ctx);
-    int _xmlManager_createUpdateContext(DbXml::XmlManager* mgr, DbXml::XmlUpdateContext** ctx);
+    int _xmlManager_createUpdateContext(XmlManagerInfo* mgr, DbXml::XmlUpdateContext** ctx);
     int _xmlDocument_setContent(DbXml::XmlDocument* doc, const char* text);
-    int _xmlContainer_updateDocument(DbXml::XmlContainer* cont, DbXml::XmlTransaction* trans,
+    int _xmlContainer_updateDocument(DbXml::XmlContainer** cont, DbXml::XmlTransaction* trans,
         DbXml::XmlDocument* doc, DbXml::XmlUpdateContext* uctx);
-    int _xmlContainer_putDocument(DbXml::XmlContainer* cont, DbXml::XmlTransaction* trans,
+    int _xmlContainer_putDocument(DbXml::XmlContainer** cont, DbXml::XmlTransaction* trans,
         DbXml::XmlDocument* doc, DbXml::XmlUpdateContext* uctx, u_int32_t flags);
-    int _xmlContainer_deleteDocument(DbXml::XmlContainer* cont, DbXml::XmlTransaction* trans,
+    int _xmlContainer_deleteDocument(DbXml::XmlContainer** cont, DbXml::XmlTransaction* trans,
         DbXml::XmlDocument* doc, DbXml::XmlUpdateContext* uctx);
 }
 
diff --git a/README b/README
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
 Berkeley DB / Berkeley DB XML binding for Haskell
-Version 0.2  23 Sep 2008
+Version 0.3  01 Oct 2008
 by Stephen Blackheath
 
 email me: http://blacksapphire.com/antispam/
@@ -7,7 +7,7 @@
 
 
 Berkeley DB XML is a powerful, fully transactional, XML-based database that uses
-XQuery as its query language.  You can download it here:
+XQuery as its query language.  It is NOT an SQL database.  You can download it here:
 
 http://www.oracle.com/database/berkeley-db/xml/index.html
 
@@ -15,26 +15,22 @@
 subset of the API, and I hope to improve it over time.  I have stuck closely to
 the C++ API, with some minor changes where a Haskell idiom seemed appropriate.
 I hope that people will develop higher level wrappers for it.  I have had great
-success with the "pickler" interfaces in the HXT library.  In a future version
-of this package I will give some examples.
-
-This package is in its very early stages, and needs some work, but it should
-allow you to write a fairly serious application.  If you find some part of the
-API that is missing, and would like it added, please contact me.
+success with the "pickler" interfaces in the HXT library.  See the adventure
+example in the examples/ directory.
 
-I hope this package helps make Haskell better.  I am partly motivated by a
-belief that SQL is holding us back.  An advanced language should have an
-advanced database.
+The binding is only about 70% complete, but it should allow you to write a fairly
+serious application.  If you would like a particular part of the API added,
+please contact me.
 
-If you just want Berkeley DB without Berkeley DB XML, you should be able to
-achieve this easily by modifying the BerkeleyDBXML.cabal file.  The Berkeley DB
-parts do not depend on the Berkeley DB XML parts.  Some time I will make this
-easier.
+If you just want Berkeley DB without Berkeley DB XML, you can do this by deleting
+the lines in BerkeleyDBXML.cabal that pertain to Berkeley DB XML.  (The Berkeley DB
+parts do not depend on the Berkeley DB XML parts.)
 
 To install, use the standard Cabal install procedure:
 
 runhaskell Setup.hs configure
 runhaskell Setup.hs build
+runhaskell Setup.hs haddock            (optional documentation in dist/doc)
 sudo runhaskell Setup.hs install
 
 If Berkeley DB or DB XML is not installed in the default location of /usr or
diff --git a/examples/adventure/Adventure.hs b/examples/adventure/Adventure.hs
--- a/examples/adventure/Adventure.hs
+++ b/examples/adventure/Adventure.hs
@@ -102,7 +102,7 @@
              "Along the beach to the north you can see some large rocks. There is thick jungle to the west.")
             [("west", "jungle"),("north", "rocks1")],
         Room "jungle"
-            "You are in a dense, jungle."
+            "You are in a dense jungle."
             [("west", "jungle"),("east", "beach"),("north", "jungle"),("south", "jungle"),("up","tree")],
         Room "tree"
             "You are up in a tree. To the south, you can see mountains."
@@ -312,8 +312,12 @@
     case yes of
         [] -> return ["I can't see one of those here."]
         ((iDoc, i):_) -> do
-            update db iDoc i {itemLocation = "player_"++name}
-            return ["You pick up "++(itemDescription i)++"."]
+            if itemPortable i
+                then do
+                    update db iDoc i {itemLocation = "player_"++name}
+                    return ["You pick up "++(itemDescription i)++"."]
+                else
+                    return ["Hurrrrgh. No, it isn't portable."]
 
 drop :: (XmlManager, XmlContainer, XmlTransaction) -> String -> String -> IO [String]
 drop db name noun = do
@@ -331,7 +335,6 @@
 
 inventory :: (XmlManager, XmlContainer, XmlTransaction) -> String -> IO [String]
 inventory db name = do
-    -- Not very good error checking here.
     items <- query db xpItem "collection()/item[@location=$loc]"
         [("loc", xmlString$ "player_"++name)]
     return$
diff --git a/examples/adventure/Makefile b/examples/adventure/Makefile
--- a/examples/adventure/Makefile
+++ b/examples/adventure/Makefile
@@ -3,3 +3,5 @@
 adventure: Adventure.hs
 	ghc -threaded --make -o $@ $<
 
+clean:
+	rm -f adventure *.hi *.o
diff --git a/examples/tests/Makefile b/examples/tests/Makefile
--- a/examples/tests/Makefile
+++ b/examples/tests/Makefile
@@ -3,3 +3,5 @@
 test1: Test1.hs
 	ghc --make -o $@ $<
 
+clean:
+	rm -f test1 *.o *.hi
