I would be happy to use locking if it's the more appropriate
construct. I tried it before ensure, in fact, because it seemed more
intuitive.

ataggart, could you take a look at my first message? The code I posted
using locking didn't work for some reason, and I imagine I was doing
something wrong.

Christophe, thanks for the partial memoization tip. I think that would
work in many cases, but for my current use case I really need to put a
lock on the ref, because the function is very expensive and other
threads will be updating it with previously unseen values so quickly
that memoization can't help. Are you saying that the fact that ensure
works in my example isn't to be counted on?


On 3/15/10, ataggart <alex.tagg...@gmail.com> wrote:
> 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
>

-- 
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