Am 01.10.2010 01:56 schrieb Darren Duncan:
> What you're talking about here sounds a lot like the class
> implementation method of "inside-out objects". -- Darren Duncan
>
You name it!

In contrast to a memory-only inside-out object, we don't have to care
about cleaning up a class hash in DESTROY - in our case the cache
Frost::Twilight - if the object goes out of scope, because it's
persistent. The attribute's data is kept in the cache for later re-use.
Moreover we have no class hash for every class, but a central cache
managed only by Frost::Asylum.

And it doesn't use /refaddr/ like i.e. MooseX::InsideOut, but the
original id given to the object at Foo->new.

The keys of the Twilight look like "Classname|Id" while the Berkley DB
files are organized in directories:

My::Own::Class has id and bar, where bar is index

Twilight:  "My::Own::Class|42" => { id => 42, bar => 'XXX' }
           "My::Own::Class|43" => { id => 43, bar => 'AAA' }
           "My::Own::Class|44" => { id => 44, bar => 'XXX' }

Burial:    /existing/path/for/my/data/My/Own/Class/id.cem   1)
           /existing/path/for/my/data/My/Own/Class/bar.cem  2)
           /existing/path/for/my/data/My/Own/Class/bar.ill  3)

1) BDB for id, content:         42      => 42
                                43      => 43
                                44      => 44
2) BDB for bar, content:        42      => 'XXX'
                                43      => 'AAA'
                                44      => 'XXX'
3) BDB index for bar, content:  'AAA'   => 43
                                'XXX'   => 42
                                'XXX'   => 44

The partly redundant storage makes the access methods easier and faster.

Moreover the data in Twilight itself can get lost, if the count of
cached object data records exceeds the limit of Forum::Twilight - which
is a LRU object. In this case Frost::Asylum automatically saves the data
to disk, if the data is dirty - a.k.a. changed - and loads it back, if
the attribute is accessed again later.

All that is transparent to the user and happens in the background - no
need to say $obj->save or take care of weak refs.

To delete an object from the storage finally, the API of Frost::Asylum
is used:

$asylum->excommunicate ( $class, $id );    # 'My::Own::Class', 42 i.e.

In this case the object #42 is removed from all above named BDB files
and the spirit with the key 'My::Own::Class|42' is removed from cache.

Ernesto 8-)


> Ernesto wrote:
>> *No Memory Leaks by Design*
>>
>> The mechanism of creating, storing and loading of objects is explained
>> on
>> http://dienstleistung-kultur.de/frost/Frost.html#The_underlying_magic_disclosed
>>
>>
>> Every time you access an object via My::Class->new, you'll get _another_
>> instance. This is not a complete object, only a proxy, which holds just
>> the attributes "id" and "asylum", all other attributes are stored in
>> Frost::Twilight - a cache, basically a simple hash of hashes.
>>
>> The value of a not-present attribute is fetched from this cache and if
>> it's not found, from Frost::Cemetery, which is a wrapper around a
>> BerkleyDB table.
>>
>> If the attribute holds an object, the object is instantiated - as proxy
>> object as well. Therefore all objects to be saved must inherit from a
>> base object, which inherits from Frost::Locum - the proxy object.
>>
>> The methods in Frost::Meta::Instance named inline_* are overwritten to
>> manage the values as described.
>>
>> You'll never get the same object's address but always the same content.
>>
>> And if this proxy object goes out of scope, it's garbage collected.
>>
>> So memory leaks shouldn't appear.


-- 
Ernst-J. "Ernesto" Johnsdorf
mailto:[email protected]
http://search.cpan.org/~ernesto/
http://dienstleistung-kultur.de

Reply via email to