[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: What are the arguments in favor of delay/force in eval.c?
From: |
Kevin Ryde |
Subject: |
Re: What are the arguments in favor of delay/force in eval.c? |
Date: |
Sat, 10 Dec 2005 11:11:17 +1100 |
User-agent: |
Gnus/5.110004 (No Gnus v0.4) Emacs/21.4 (gnu/linux) |
Rob Browning <address@hidden> writes:
>
> This would only work if you forbid side-effects, right?
Well, leave it up to the application to keep itself out of trouble if
the code is not reentrant. That'd be consistent a general policy of
not stopping stupid multi-thread code, only code that might crash the
interpreter.
> I was also wondering about the possibilities for deadlock with the
> current code, and then what they might be with a srfi-45 force,
Whenever arbitrary code executes in a mutex I guess there's scope for
that. srfi-45 shouldn't be inherently worse.
Some code below (untested) for what I think "force" could look like
without per-promise mutexes.
Having a magic "uncomputed" value means no locking at all once
computed (same as your code). The thunk to be called is in a separate
field, zapped once no longer needed.
Second block of code is with two magic "uncomputed" values, one for
normal and one for srfi-45 style lazy promises. If I understand how
they're supposed to work :-).
#define SCM_PROMISE_DATA SCM_SMOB_OBJECT
#define SCM_PROMISE_EXPR SCM_SMOB_OBJECT_2
{
SCM data, expr, ans;
SCM_VALIDATE_SMOB (1, promise, promise);
data = SCM_PROMISE_DATA (promise);
if (data != SCM_PROMISE_MAGIC_UNCOMPUTED_INDICATOR)
return data;
SCM_CRITICAL_SECTION_START;
data = SCM_PROMISE_DATA (promise);
expr = SCM_PROMISE_EXPR (promise);
SCM_CRITICAL_SECTION_END;
if (data != SCM_PROMISE_MAGIC_UNCOMPUTED_INDICATOR)
return data;
ans = scm_call_0 (expr);
SCM_CRITICAL_SECTION_START;
data = SCM_PROMISE_DATA (promise);
if (data == SCM_PROMISE_MAGIC_UNCOMPUTED_INDICATOR)
{
SCM_SET_PROMISE_DATA (promise, ans); /* we set the value */
SCM_SET_PROMISE_EXPR (promise, SCM_BOOL_F); /* gc the expression */
}
else
{
/* recursive force or other thread set the value, return that */
ans = data;
}
SCM_CRITICAL_SECTION_END;
return ans;
}
{
SCM data, expr, ans;
SCM_VALIDATE_SMOB (1, promise, promise);
again:
data = SCM_PROMISE_DATA (promise);
if ((data & ~1) != SCM_PROMISE_MAGIC_UNCOMPUTED)
return data;
SCM_CRITICAL_SECTION_START;
data = SCM_PROMISE_DATA (promise);
expr = SCM_PROMISE_EXPR (promise);
SCM_CRITICAL_SECTION_END;
if ((data & ~1) != SCM_PROMISE_MAGIC_UNCOMPUTED)
return data;
ans = scm_call_0 (expr);
SCM_CRITICAL_SECTION_START;
data = SCM_PROMISE_DATA (promise);
if (data == SCM_PROMISE_MAGIC_UNCOMPUTED_LAZY && SCM_PROMISE_P (ans))
{
/* SRFI-45 lazy promise, mutate ourselves to ANS and go again */
SCM_SET_PROMISE_DATA (promise, SCM_PROMISE_DATA (ans));
SCM_SET_PROMISE_EXPR (promise, SCM_PROMISE_EXPR (ans));
SCM_CRITICAL_SECTION_END;
goto again;
}
else if (data == SCM_PROMISE_MAGIC_UNCOMPUTED_NORMAL)
{
SCM_SET_PROMISE_DATA (promise, ans); /* we set the value */
SCM_SET_PROMISE_EXPR (promise, SCM_BOOL_F); /* gc the expression */
}
else
{
/* recursive force or other thread set the value, return that */
ans = data;
}
SCM_CRITICAL_SECTION_END;
return ans;
}