Re: p5p summary: Improving threads::shared ?
[email protected] (Dean Arnold) Mon, 05 May 2008 12:36:06 -0700
| Newsgroups | perl.ithreads |
|---|---|
| Message-ID | <[email protected]> |
Jerry D. Hedden wrote: > erry D. Hedden wrote: >> Look at $x: >> REF(0x144f8f0) >> REF(0x144f8f0) >> REF(0x144f8f0) >> REF(0x144f8f0) >> REF(0x144f8f0) >> REF(0x144f8f0) >> >> First look at $y: >> SCALAR(0x1423c70) >> SCALAR(0x1423ad8) >> SCALAR(0x14bd968) >> SCALAR(0x14bd980) >> SCALAR(0x14bd998) >> SCALAR(0x14bd9b0) >> >> Second look at $y: >> REF(0x1423c70) >> REF(0x1423ad8) >> REF(0x14bd968) >> REF(0x14bd980) >> REF(0x14bd998) >> SCALAR(0x14bd9b0) >> >> Seems to me that this is a bug. It shows that >> threads::shared isn't detecting that it's dealing with a >> circular reference. With each level that the app traverses, >> threads::shared "unrolls" another version of the shared >> variable. > >> The more I think about it, the more I'm convinced this needs >> to be fixed. The original variable $x is a circular >> reference, and it's finiteness is detectable. The copy made >> to $y has become an infinitely deep reference with lazy >> evaluation. > > I've been looking at how to fix this, but know understanding > of the internals of threads::shared is weak. > > Conceptually, I think it would require keeping a weak > reference of each private SV associated with a shared SV. > This would need to be done on a per-thread basis. Then when > a thread tries to reference a shared SV, a lookup would be > made to see if a private SV already exists (and still > exists) for that thread. If so, that is returned (and the > ref count of the weak ref is incremented?). If not, a new > private SV is created, and a weak ref to it is appropriately > stored. > > Is this a logical approach? If so, is it doable? > By coincidence, I've been doing related work on Thread::Sociable's STM implementation. It has to keep a "shadow" proxy of each variable in order to avoid the same referencing issue (otherwise, it could create multiple different transactional versions of the same referenced variable) For threads::shared, the only solution I can think of is adding a fieldhash to the thread-private my_ctx structure keyed by the address of the referent variable's shared version. Then each attempt to create a new proxy would lookup any existing persistent proxy for the shared SV, and return it if found (currently, each new reference to a shared variable creates a new proxy, which is what causes this mess). It may create refcounting issues; the private proxy would need to be refcounted every time the shared variable was refcounted in the same thread. (Alternately, the thread could refcount only the proxy, and then decrement the shared versions refcount only when the private proxy's refcount dropped to zero) I also don't know how it would effect taking ref's of shared array/hash elements. And this will probably slow things down even further. - Dean