guile-devel
[Top][All Lists]
Advanced

[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;
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]