guile-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: GH replacement proposal (includes a bit of Unicode)


From: Marius Vollmer
Subject: Re: GH replacement proposal (includes a bit of Unicode)
Date: Fri, 23 Apr 2004 18:57:16 +0200
User-agent: Gnus/5.1003 (Gnus v5.10.3) Emacs/21.3 (gnu/linux)

Rob Browning <address@hidden> writes:

>>   These two functions lock and unlock all SCM objects (the heap).  The
>>   heap should not be locked for long periods of time and no calls to
>>   'normal' libguile functions are allowed while it is locked.  A
>>   function is 'normal' unless it is specifically documented to be
>>   useable with a locked heap.  (Indeed, most 'unnormal' functions can
>>   _only_ be used while the heap is locked.)
>>
>>   You can not lock the heap twice.  Calling scm_lock_heap while the
>>   heap is already locked results in undefined behavior.  Likewise,
>>   calling scm_unlock_heap when the heap is not locked is verboten.
>>
>>   - const unsigned char *scm_l_get_utf8_string_mem (SCM str);
>
> I'm a little wary of the locking, especially global locking, but I
> suppose it may well be necessary.  I don't have a strong feeling
> either way offhand, but presuming for the moment that it is necessary,
> then is there any way to lock down a particular value rather than the
> entire heap?

Having a lock for every object would have a high overhead and give you
very little in terms of performance, I guess.  Also, they would be
tricky to use.

When you need to lock two objects, there would be the danger of
deadlocks, when other code needs to lock the exact same two objects,
but does it in reverse order.

You would also have to allow locking an object twice, further
increasing overhead.

> Also, could and should we make it easy to install a frame unwind
> handler that unlocks the heap when acquiring the lock?

That is not necessary since a non-local exit is not allowed to happen
when the heap is locked.  (The proposal needs to state that
scm_l_get_string_utf8_mem does not throw, it returns NULL for
non-strings.)

Locking the heap really means putting you into a completely different
world; none of Guile's functions can be us while the heap is locked.

> Finally, what's the argument against allowing recursive locking by the
> same thread, too expensive?

It would not work.  Locking the heap essentially has lexical scope:
either some piece of code has been written to use Guile normally, or
it has been written to work with a locked heap.  (Or it doesn't care
about Guile at all.)

When some function calls scm_unlock_heap, it likely expects the heap
to be unlocked after that call and starts to use normal libguile
functions again (doing allocation, for example).  When the heap has
not in fact been unlocked, well...

scm_lock_heap / scm_unlock_heap is a typical C style API: you must use
it correctly and when you don't the behavior is nasty.  Luckily, you
don't need to use it often.

> On a related note, in many cases, I suspect all the user may really
> need is a cheap way to copy some offset + size chunk of the data into
> their own buffer, especially when dealing with homogeneous uint8
> arrays.  If so, then it might make sense to provide a set of functions
> that can do that, handling whatever locking and memcpying is needed.

Yes, that would be a good addition.  However, I'd still want to have
the low-level functions (scm_lock_heap, scm_l_* etc.) available.  You
can use them to code the more convenient variants, but it is unlikely
that we can provide convenience variants for all cases.

For example, you might want to pass a string to gdk_draw_text, or to
libc fputs, or to some other function that works with raw strings that
you know is OK to be called with a locked heap.

This would be a typical use

  int
  write_scm_string (int fd, SCM str)
  {
    int n;
    const char *mem;
    size_t len;

    scm_lock_heap ();
    mem = scm_l_get_string_utf8_mem (str);
    len = scm_l_get_string_utf8_len (str);
    if (mem)
      n = write (fd, mem, len);
    else
      {
        n = -1;
        errno = EINVAL;
      }
    scm_l_unlock_heap ();
    return n;
  }

[ Maybe we should have

    if (scm_l_get_string_utf8_raw (str, &mem, &len))
      ...

  instead?
]




reply via email to

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