If using ensure solves the problem then something else is going on,
because ensure doesn't lock a ref for the life of the transaction any
more than ref-set does. As the doc for ensure notes, it allows for
*more* concurrency than ref-set, not less.  From clojure.org/refs:

"All changes made to Refs during a transaction (via ref-set, alter or
commute) will appear to occur at a single point in the 'Ref world'
timeline (its 'write point')."

Ensure simply adds (after a bit of status checking) the ref to the set
of refs that need to be locked and examined when commit occurs.  From
clojure.lang.LockingTransaction.doEnsure(Ref):

void doEnsure(Ref ref){
        if(!info.running())
                throw retryex;
        if(ensures.contains(ref))
                return;
        ref.lock.readLock().lock();

        //someone completed a write after our snapshot
        if(ref.tvals != null && ref.tvals.point > readPoint) {
        ref.lock.readLock().unlock();
        throw retryex;
    }

        Info refinfo = ref.tinfo;

        //writer exists
        if(refinfo != null && refinfo.running())
                {
                ref.lock.readLock().unlock();

                if(refinfo != info) //not us, ensure is doomed
                        {
                        blockAndBail(refinfo);
                        }
                }
        else
                ensures.add(ref);
}

As for different constructs, they exist, one is 'ensure, the other is
'locking.


On Mar 15, 2:58 pm, Garth Sheldon-Coulson <g...@mit.edu> wrote:
> Well it definitely seems that ensure has the behavior Michal
> described, because the ensure code I posted works. I'm glad this
> behavior is available, because I don't think there is any other way to
> achieve the combination of synchronization and locking I need. (I
> couldn't get locking to work on a ref; see my original msg.)
>
> Maybe the two different behaviors call for different constructs: one
> for making sure an unmodified ref hasn't changed at commit time (the
> original purpose I thought ensure was supposed to serve), and one with
> the behavior I need here, namely causing all other modifications to
> block for the remaining life of the transaction.
>
> On 3/15/10, ataggart <alex.tagg...@gmail.com> wrote:
>
>
>
>
>
>
>
> > On Mar 15, 1:43 pm, Michał Marczyk <michal.marc...@gmail.com> wrote:
> >> On 15 March 2010 21:08, Meikel Brandmeyer <m...@kotka.de> wrote:
>
> >> > Now I'm confused. Calling ensure on r shouldn't have an effect since we
> >> > call alter on r anyway, no?
>
> >> ensure "protects the ref from modification by other transactions"
> >> (from the docs). alter does not.
>
> >> Reading into the Java code, ensure puts a lock on the ref, which, once
> >> in place, guarantees that the transaction doing the ensuring has an
> >> exclusive right to modify the ref until it commits / retries... or
> >> something, my Java-fu is still nothing to boast about, regrettably.
>
> >> At any rate, my current understanding is that, in Garth's example, the
> >> ensure gives (alter r f) all the time it needs to modify r's value
> >> while putting all other transactions which attempt to modify r on
> >> hold. alter, by itself, never interferes with background transactions;
> >> should something disappear from under its feet, it expects to be
> >> retried.
>
> >> Ok, back to improving my Java chops in the hope of grasping all the
> >> intricasies of Rich's code sometime... *sigh*
>
> >> Sincerely,
> >> Michał
>
> > I'm inclined to say this is incorrect as I'm on my iphone so I can't
> > look at the source. The concurrency functions (e.g., ref-set, alter,
> > ensure) only lock their refs during the commit process.  The ensure
> > function is provided to add a *non-changing* ref to the set of refs
> > that need to be locked; ref-set, etc., do this implicitly.  To lock
> > the refs upon first use would largely obviate the point of the STM.
>
> > The issue Garth describes is a case of live-locking, an extant failure
> > mode of the STM.  Some solutions would be to break up the work from
> > just a single transaction (though sacrificing consistency), or use the
> > locking construct:
> >http://richhickey.github.com/clojure/clojure.core-api.html#clojure.co...
>
> > --
> > You received this message because you are subscribed to the Google
> > Groups "Clojure" group.
> > To post to this group, send email to clojure@googlegroups.com
> > Note that posts from new members are moderated - please be patient with your
> > first post.
> > To unsubscribe from this group, send email to
> > clojure+unsubscr...@googlegroups.com
> > For more options, visit this group at
> >http://groups.google.com/group/clojure?hl=en
>
> --
> Sent from my mobile device

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply via email to