This idea seems to fit in a lot of places. It's more of a design
pattern than anything else, but one I think P6 can use to good effect
in the "standard library".


Lightweight Object Existance (LOE) Proxies

An LOE proxy is an object that proxies for another, heavier, object
that (maybe) doesn't exist.

The idea is that when "creating" an object, either from scratch or
rehydrating/thawing an object stored offline or serializing an object
stored on a separate node, is expensive or undefined, an LOE proxy can
be used.

This proxy could be used when a network of objects is being
instantiated, when a particularly smart garbage collector knew how to
push unused but persistent objects out of memory, and by some other,
sleazier, code (below).

It occurred to me yesterday, while reading DDJ, that this is a good way
to implement a ThreadLocal storage variable: 

A thread will have its own scope. This behaves as you expect a scope to
behave with respect to other thread scopes, and serves as a divider
between the lexical scope of subs entered in the thread and scopes
active for this thread because they were entered in the parent thread
before the current thread was spawned.

An object declared C<is ThreadLocal> would simply create a shared
reference to an anonymous object in the threads scratchpad, and use
run-time resolution.

Thus:

sub A {
  ...
}

my $a is ThreadLocal;

for (0..10) { 
  thread &A;
}

Each thread would share the global scope, and behind the global scope
the zero-thread scope (which contains nothing).

The C<thread> call would create a thread scope, which would then be
overlain with a subroutine scope for sub A. 

Scope stack:
    Thread[Main]
    ::Global
    Thread[0..10]
    ::A

The ThreadLocal object lives in ::Global context. If it were a valid
object that had to implement its own semantics, it would likely be slow
(& buggy!) unless there were also some sort of direct "copy on access"
support implemented in core (and perhaps slow even then).

But if the object were itself an LOE proxy, the proxy could dynamically
instantiate the new object and dispatch appropriately:

class ThreadLocal {
    has    %.thread2client;

    method DISPATCH($self: $method, @args)
    {
        my $t = callcc($caller.cc, get_current_thread);
        my $client = %.thread2client{$t} //= new $.class;
        SUPER.DISPATCH($client, $method, @args);    
    }
}

=Austin

Reply via email to