On Mon, Mar 15, 2010 at 01:21:22PM -0400, Garth Sheldon-Coulson wrote:
> Ah, maybe I should have read the thread on ensure before I posted this! =)
>
> (dosync (ensure r) (alter r f))
>
> works.
Now I'm confused. Calling ensure on r shouldn't have an effect since we
call alter on r anyway, no?
Sincerely
Meikel
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ł
Ok, but maybe the point of Meikel is that doing so may (?) be relying
on undocumented implementation detail ... ?
2010/3/15 Michał Marczyk <michal....@gmail.com>:
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
Well, I don't think so -- that passage I quoted from ensure's docs
seems to be an attempt at documenting it. In fact, as far as I can
tell, this is the single purpose of ensure.
OTOH, if my mental picture of what's going in is correct, I guess I'd
be in favour of an extra clarification effort on that docstring...
Then again I'm still in the process of thinking over what I saw today
(w.r.t. STM), so maybe it just needs some time to sink in.
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.core/locking
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.
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@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+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>
--
Sent from my mobile device
"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.
>
> >http://richhickey.github.com/clojure/clojure.core-api.html#clojure.co...
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:I'm inclined to say this is incorrect as I'm on my iphone so I can't
>
> > 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ł
look at the source. The concurrency functions (e.g., ref-set, alter,
ensure) only lock their refs during the commit process.
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.core/locking
I make no claims about the Rightness of this suggestion, but
simply offer another example of a work-around:
(dosync (alter r identity) (alter r f))
That is, a "dummy write" via alter is also sufficient to allow
the transaction to succeed, just like 'ensure'.
--Chouser
On Mar 15, 3:17 pm, Christophe Grand <christo...@cgrand.net> wrote:
> >http://richhickey.github.com/clojure/clojure.core-api.html#clojure.co...
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.t...@gmail.com> wrote:
The point of ensure, as I see it, is to say only that the value will
be consistent *when the commit occurs*. As for the whether the
immediate read-lock-grabbing behavior of ensure should be replied
upon, I can't say, though I'm inclined to no more rely on that than I
am on the barging logic. Rich's input would be valuable here.
On Mar 15, 3:24 pm, Garth Sheldon-Coulson <g...@MIT.EDU> wrote:
> 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?
>
Yes, it would be helpful to get some more clarity on the
transaction-long readlocking of ensure.
On 3/15/10, ataggart <alex.t...@gmail.com> wrote:
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?
I make no claims about the Rightness of this suggestion, but
simply offer another example of a work-around:
(dosync (alter r identity) (alter r f))
That is, a "dummy write" via alter is also sufficient to allow
the transaction to succeed, just like 'ensure'.
Well, what you've got there seems much cleaner than a dummy
write, and makes 'alter' do a lot less work than it did. I won't
pretend to understand the STM well enough to know if it's all
correct though.
--Chouser
http://joyofclojure.com/