((section 2 "Outdated egg!" (p "This is an egg for CHICKEN 4, the unsupported old release.  You're almost certainly looking for " (int-link "/eggref/5/hopefully" "the CHICKEN 5 version of this egg") ", if it exists.") (p "If it does not exist, there may be equivalent functionality provided by another egg; have a look at the " (link "https://wiki.call-cc.org/chicken-projects/egg-index-5.html" "egg index") ". Otherwise, please consider porting this egg to the current version of CHICKEN.") (tags "egg")) (section 2 "hopefully" (p "Simple composable transactional memory.") (p "The API is similar to Clojure and STMX.  However (currently) limited, focused on a low level, procedural interface.") (toc) (section 3 "Overview" (p "This egg provides two modules: " (tt "hopefully") " and " (tt "hopefully-current") ".") (p "Module " (tt "hopefully") " contains bindings recommended to use.  These transactions are roughly as fast as normal locking.  (Depending more on compiler optimizations and usage szenarios.)") (p "Module " (tt "hopefully-current") " adds support for the concept of an implicit current transaction, which is nice but and order of magnitude more expensive at runtime.")) (section 3 "Issues" (p (tt "define-a-record") " and " (tt "define-ac-record") " both define a " (tt "TYPE-FIELD") " accessor, though with incompatible semantics.  While the AC-variant is changes meaning depending on whether or not there is a " (tt "current-transaction") " on the thread.  The A-variant always returns the external value.  The former is OK, since the whole purpose is to be downward compatible to " (tt "define-record") "-based code not aware of transactions.  But once most of a code base is converted to use references, once only wants to replace " (tt "define-ac-record") " with " (tt "define-a-record") ".  At that time those field readers should not suddenly change meaning anymore.   The old \"global\" accessors should become inaccessible.  The \"alway-return-global-value\" accessors need to be renamed (and the renamed value defined by " (tt "define-ac-record") " as well to aid the transition).  Just how rename it?  Append \"" (tt "@") "\"?")) (section 3 "Modules" (section 4 "hopefully" (def (sig (syntax "define-a-record" (id define-a-record))) (p "Like define-record, defines procedures according to the following pattern.")) (def (sig (procedure "(make-TYPE FIELDS ...) -> AREC" (id make-TYPE)))) (def (sig (procedure "(TYPE-FIELD-ref AREC TNX) => REF" (id TYPE-FIELD-ref))) (p "Return a reference for use with CELL-REF (alias \"@\") and ALTER!.") (p "Note: Try to use this accessor just once per object+field.  Multiple calls (within a lightweight transaction) will produce independent references.  (If these become inconsistent, the commit will fail nevertheless.)  Only those references used to " (tt "(set! (@ REF) val)") " will return the in-transaction value.")) (def (sig (procedure "(TYPE-FIELD AREC)" (id TYPE-FIELD))) (p "Return the FIELD value visible without transactions in effect.")) (def (sig (procedure "(TYPE-tag AREC)" (id TYPE-tag))) (p "Purely for debugging.  Mayb e removed. Return the internal version tag of the slot.")) (def (sig (procedure "(cell-ref REF)" (id cell-ref))) (p "Retrieve the in-transaction value from the " (tt "REF") "erence (and add it to the transactions dependencies).")) (def (sig (procedure "(@ REF)" (id @))) (p "Alias to cell-ref.  With generalized setter.")) (def (sig (procedure "(alter! REF val)" (id alter!))) (p "Alter a " (tt "REF") "erence (produced by the " (tt "type") "-" (tt "field") "-ref accessors to hold the new value " (tt "val") ".  This also adds the cell to the dependencies of the transaction associated with the " (tt "REF") ".")) (def (sig (procedure "(call-with-transaction PROC)" (id call-with-transaction)) (procedure "(call-with-transaction/values PROC)" (id call-with-transaction/values))) (p "Call PROC with one argument, a fresh (lightweight) transaction. PROC may be called multiple times in case of a conflict. (See hopefully-current for the difference to heavy transactions).") (p "Returns whatever PROC returns.  Use " (tt "call-with-transaction") " for multiple value returns " (tt "call-with-transaction/values") " returns all values.") (p "Note: One " (tt "should not") " pass the transaction argument around among threads or capture it.  Most (if not all) resulting conditions should be handled.  But it is no good idea."))) (section 4 "hopefully-current" (p "This module introduces the concept of a default " (tt "current-transaction") " and heavy transactions.") (p "When a reference is added to a heavy transaction, the transactions dependencies are searched and if a reference to the same object+slot is found, it is returned.") (def (sig (syntax "define-ac-record" (id define-ac-record))) (p "Like " (tt "define-a-record") ".") (p (tt "define-ac-record") " is provided for maximum compatibility with " (tt "define-record") ".  Just changing the record definition should make code aware of the current transaction.")) (def (sig (procedure "(make-TYPE FIELDS..) -> ACREC" (id make-TYPE))) (p "Accessors:")) (def (sig (procedure "(TYPE-FIELD-ref ACREC TNX) => REF" (id TYPE-FIELD-ref))) (p "Return a reference to the in-transaction value of " (tt "field") " in " (tt "ACREC") " for use with CELL-REF (alias \"@\") and ALTER!.  See sibling definition in " (tt "hopefully") ".")) (def (sig (procedure "(TYPE-FIELD ACREC)" (id TYPE-FIELD))) (p "Return the value of " (tt "field") " in ACREC.  Returns the in-transaction value with respect to the " (tt "current-transaction") " or the outside value if there is no " (tt "current-transaction") " in the " (tt "current-thread") ".") (p "Note: this is roughly an order of magnitude slower than the corresponding accessor from " (tt "define-a-record"))) (def (sig (procedure "(TYPE-FIELD-set! ACREC val) -> undefined" (id TYPE-FIELD-set!))) (p "Set the value of " (tt "field") " to " (tt "val") ".  Changes the in-transaction value respect to the " (tt "current-transaction") " or the outside value if there is no " (tt "current-transaction") " in the " (tt "current-thread") ".") (p "Note: this is roughly an order of magnitude slower than the corresponding accessor from " (tt "define-a-record"))) (def (sig (procedure "(with-current-transaction THUNK)" (id with-current-transaction))) (p "Establish a new " (tt "current-transaction") " and call " (tt "THUNK") ". After thunk completed, commit the current transaction. If that failes, THUNK is called again.") (p "Returns whatever THUNK returns.")))) (section 3 "Examples" (highlight scheme "(define-a-record gbox v)\n(define b1 (make-gbox 0))\n(define b2 (make-gbox 1))\n\n(call-with-transaction\n (lambda (tnx)\n   (let ((x (gbox-v-ref b1 tnx))\n         (i (gbox-v-ref b2 tnx)))\n     (let ((ni (@ i)))\n       (alter! x (+ (@ x) ni))\n       (alter! i (add1 ni))))))") (p "See also tests/run.scm.")) (section 3 "Compile time options" (p "-D no-dirty-tagging : save some internal consitency checks -D debug: add additional consitency checks")) (section 3 "About this egg" (section 4 "Source" (p "Latest version: " (link "http://askemos.org/chicken-eggs/hopefully/hopefully.tar.gz" "hopefully from askemos.org"))) (section 4 "Authors" (p "Jörg F. Wittenberger")) (section 4 "Version History" (p "0.2.3: 2015-12-28 -- Modified tests/run.scm as it did work on some, but not all platforms.") (p "0.2.2: 2015-12-21 -- Bugfix: use of ##sys#setislot with non-immediate objects.  Some more tweaks.") (p "0.2.1: 2015-12-19 -- Some tweaks.") (p "0.2: 2015-12-18 -- Replacing chicken hash tables with llrb trees made ac-records about 4x faster.") (p "0.1.1: 2015-12-18 -- Fix missing unquote.") (p "0.1: 2015-12-16 -- Initial Release")))))