"Julian Graham" <[EMAIL PROTECTED]> writes:

> Find attached the latest revision of the core changes for SRFI-18
> support.  Key changes between this revision and the last are:
>
> * scm_to_timespec -> to_timespec
> * "Timeout values" for timed joins
> * The extension of make-mutex and addition of make_mutex_with_flags to
> support additional configuration options that persist for the lifetime
> of a mutex (unchecked unlocking and external unlocking)
> * fat_mutex_unlock now takes a condition variable and a timeout to
> support SRFI-18's condition-signal unlock semantics; mutex unlocking
> and condition variable waiting are reimplemented in terms of
> fat_mutex_unlock; unnecessary relocking / unlocking is no longer
> performed
> * The threads tests and scheduling documentation have been updated to
> reflect the above.
>
> Let me know what you think!

It looks great.  I still have a few minor queries, but it's close
enough now that I've committed this latest patch to CVS; it'll be much
more convenient to work on the few remaining queries incrementally,
rather than with respect to threads.c as it was prior to all these
changes.

> [EMAIL PROTECTED] {Scheme Procedure} make-mutex
> [EMAIL PROTECTED] {Scheme Procedure} make-mutex . flags
>  @deffnx {C Function} scm_make_mutex ()
> -Return a new standard mutex.  It is initially unlocked.
> [EMAIL PROTECTED] {C Function} scm_make_mutex_with_flags (SCM flag)

flag -> flags here?

> +static void
> +to_timespec (SCM t, scm_t_timespec *waittime)
> +{
> +  if (scm_is_pair (t))
> +    {
> +      waittime->tv_sec = scm_to_ulong (SCM_CAR (t));
> +      waittime->tv_nsec = scm_to_ulong (SCM_CDR (t)) * 1000;
> +    }
> +  else
> +    {
> +      double time = scm_to_double (t);
> +      double sec = scm_c_truncate (time);
> +
> +      waittime->tv_sec = (long) sec;
> +      waittime->tv_nsec = (long) ((time - sec) * 1000000);

1000000 -> 1000000000 ?

> +static SCM unchecked_unlock_sym;
> +static SCM allow_external_unlock_sym;
> +static SCM recursive_sym;

Use SCM_SYMBOL here?  As the init code stands, this means that the
symbols will end up being created in scm_init_thread_procs(), but I
think that will be fine, as the symbols are only useful in procedure
calls.

> +
> +SCM_DEFINE (scm_make_mutex_with_flags, "make-mutex", 0, 0, 1,
> +         (SCM flags),
>           "Create a new mutex. ")
> -#define FUNC_NAME s_scm_make_mutex
> +#define FUNC_NAME s_scm_make_mutex_with_flags
>  {
> -  return make_fat_mutex (0);
> +  int unchecked_unlock = 0, external_unlock = 0, recursive = 0;
> +
> +  SCM ptr = flags;
> +  while (! scm_is_null (ptr))
> +    {
> +      SCM flag = SCM_CAR (ptr);
> +      if (scm_is_eq (flag, unchecked_unlock_sym))
> +     unchecked_unlock = 1;
> +      else if (scm_is_eq (flag, allow_external_unlock_sym))
> +     external_unlock = 1;
> +      else if (scm_is_eq (flag, recursive_sym))
> +     recursive = 1;
> +      else 
> +     SCM_MISC_ERROR ("unsupported mutex option", SCM_EOL);

Perhaps we can generate a more explicit error here, indicating the
actual problem value?  See other calls to scm_misc_error() where the
3rd parameter is not SCM_EOL.

> +static int
> +fat_mutex_unlock (SCM mutex, SCM cond,
> +               const scm_t_timespec *waittime, int relock)
>  {
> -  char *msg = NULL;
> +  fat_mutex *m = SCM_MUTEX_DATA (mutex);
> +  fat_cond *c = NULL;
> +  scm_i_thread *t = SCM_I_CURRENT_THREAD;
> +  int err = 0, ret = 0;
>  
>    scm_i_scm_pthread_mutex_lock (&m->lock);
>    if (!scm_is_eq (m->owner, scm_current_thread ()))
>      {
>        if (scm_is_false (m->owner))
> -     msg = "mutex not locked";
> -      else
> -     msg = "mutex not locked by current thread";
> +     {
> +       if (!m->unchecked_unlock)
> +         scm_misc_error (NULL, "mutex not locked", SCM_EOL);
> +     }
> +      else if (!m->allow_external_unlock)
> +     scm_misc_error (NULL, "mutex not locked by current thread", SCM_EOL);
> +    }

Need to unlock m->lock before raising the error?

>  SCM_DEFINE (scm_timed_wait_condition_variable, "wait-condition-variable", 2, 
> 1, 0,
> @@ -1393,20 +1590,11 @@
>    
>    if (!SCM_UNBNDP (t))
>      {
> -      if (scm_is_pair (t))
> -     {
> -       waittime.tv_sec = scm_to_ulong (SCM_CAR (t));
> -       waittime.tv_nsec = scm_to_ulong (SCM_CAR (t)) * 1000;
> -     }
> -      else
> -     {
> -       waittime.tv_sec = scm_to_ulong (t);
> -       waittime.tv_nsec = 0;
> -     }
> +      to_timespec (t, &waittime);
>        waitptr = &waittime;
>      }
>  
> -  return scm_from_bool (fat_cond_timedwait (cv, mx, waitptr));
> +  return fat_cond_timedwait (cv, mx, waitptr) ? SCM_BOOL_T : SCM_BOOL_F;

Better to eliminate fat_cond_timedwait completely now, I think.
(i.e. Just rewrite the last line as a fat_mutex_unlock() call.)

Finally, please note that we will need a NEWS entry for this work.
Are you happy to write that too?  (You may of course prefer to defer
this until the SRFI-18 Scheme parts are committed too - that's
absolutely fine.)

Regards,
      Neil



Reply via email to