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

Reply via email to