[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: the new gc asserts in master
From: |
Ludovic Courtès |
Subject: |
Re: the new gc asserts in master |
Date: |
Thu, 28 Aug 2008 16:17:33 +0200 |
User-agent: |
Gnus/5.11 (Gnus v5.11) Emacs/22.2 (gnu/linux) |
Hello,
Thanks for the nice summary!
Andy Wingo <address@hidden> writes:
> But what if it goes like this:
>
> S becomes collectable in theory
>
> mark phase: S is indeed marked as collectable
>
> C is returned from a callback: get_ptr() return S
>
> at some later time the card containing S is swept; S's free function
> is run, and S is marked as a free cell
>
> at some later point maybe S gets reused for some other purpose
>
> however S was already alive in scheme, and we are using it as a smob!
>
> The point is:
>
> You cannot do C->Scheme mapping reliably in the presence of lazy
> sweeping, because there is a time in which the object is marked as
> sweepable but not swept, but the C->Scheme code has no way of knowing
> this.
>
> (While talking with Ludovic we realized that his code has this problem.)
The code I had in mind is GnuTLS [0], but it's a slightly more specific
scenario and I now don't think the problem applies there.
In GnuTLS, there are "session" objects; session objects can have a
Scheme port attached to them, and the `session-record-port' procedure
returns that port. What we want is:
(eq? (session-record-port s) (session-record-port s))
IOW, there must be a mapping from the session to the port so that we
don't create a new port each time `session-record-port' is called.
Here's how it's achieved. Let `s' be the C session object, `S' the
corresponding SMOB, and `P' the port (an `SCM'). We have the following
object graph:
SCM_STREAM(P)
S <-------------------- P
| ^
|SCM_SMOB_DATA(S) |
| |
| _____________________'
| / gnutls_session_get_ptr(s)
v/
s
The mark procedure of `S' marks `P'. Thus, as long as `S' is reachable,
`P' is reachable. In addition, as long as `P' is reachable, `S' is
reachable.
The important difference with the generalized scheme you described is
that when `S' becomes unreferenced by Scheme code, there's no way `s'
can suddenly reappear at the Scheme level because GnuTLS doesn't have
any function that would return `s'. Thus, the race condition you
described cannot happen.
The key insight here is that `S' and `s' "aggregate" `P', i.e., the
lifetime of `S' and `s' is always greater than or equal to that of `P'.
I presume that this scheme is applicable to many (most?) object-oriented
APIs. It's actually what lead to the inception of the `aggregated'
typespec in G-Wrap [1].
Now, I haven't considered call-backs. But maybe a call-back can be seen
as a procedure that's aggregated by some object; in turn, the procedure
refer to other objects in its environment, such that the lifetime of the
objects involved is similarly hierarchical.
Sorry for the digression but I think it's important to know whether
Guile's API intrinsically makes it hard to handle such common use cases.
Thanks,
Ludo'.
[0]
http://git.savannah.gnu.org/gitweb/?p=gnutls.git;a=blob;f=guile/src/core.c#l42
[1] http://www.nongnu.org/g-wrap/manual/Wrapping-a-C-Function.html
- Re: the new gc asserts in master, (continued)
- Re: the new gc asserts in master, Han-Wen Nienhuys, 2008/08/26
- Re: the new gc asserts in master, Ludovic Courtès, 2008/08/27
- Re: the new gc asserts in master, Han-Wen Nienhuys, 2008/08/27
- Re: the new gc asserts in master, Ludovic Courtès, 2008/08/27
- Re: the new gc asserts in master, Han-Wen Nienhuys, 2008/08/28
- Re: the new gc asserts in master, Han-Wen Nienhuys, 2008/08/28
- Re: the new gc asserts in master, Ludovic Courtès, 2008/08/28
- Re: the new gc asserts in master, Andy Wingo, 2008/08/27
- Re: the new gc asserts in master, Andy Wingo, 2008/08/27
- Re: the new gc asserts in master, Han-Wen Nienhuys, 2008/08/28
- Re: the new gc asserts in master,
Ludovic Courtès <=
- Re: the new gc asserts in master, Han-Wen Nienhuys, 2008/08/28
- Re: the new gc asserts in master, Han-Wen Nienhuys, 2008/08/28