Slots and Metalink

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Slots and Metalink

Vitor Medina Cruz
Hello,

Is it possible to intercept a slot store? I tried with a before metalink into #write:to selector, but it don't seems to work. Should I use another selector?

I would like to experiment with ivar change notification, but I don't know what is the better approach. I know I could install a MetaLink in an attribution node, but that seems ankward and I would have to edit the linkage every time my object is changed, isn't true?

Regards,
Vitor
Reply | Threaded
Open this post in threaded view
|

Re: Slots and Metalink

Steven Costiou-2

Hi,

if you are using Pharo7, you could do either on a class (affects all instances) or on an object (affects only the target instance):

classOrObject link: yourMetaLink toSlotNamed: #slotName option: #write

It will install the metalink on all write accesses to the slot.

Note that if you target a single object, it will be migrated to an anonymous subclass for the metalink to be object-specific.

 

In both cases, if you add or remove inst-var accesses, the metalink should update automatically.

 

Steven.

 

 

Le 2019-04-03 15:57, Vitor Medina Cruz a écrit :

Hello,

Is it possible to intercept a slot store? I tried with a before metalink into #write:to selector, but it don't seems to work. Should I use another selector?

I would like to experiment with ivar change notification, but I don't know what is the better approach. I know I could install a MetaLink in an attribution node, but that seems ankward and I would have to edit the linkage every time my object is changed, isn't true?

Regards,
Vitor

 

Reply | Threaded
Open this post in threaded view
|

Re: Slots and Metalink

Steven Costiou-2

Also, I do not think metalinks could work on #write:to: method from slots, because that method is not used at runtime (I do not remember exactly but maybe somebody knows the details...).

 

Le 2019-04-03 16:20, Steven Costiou a écrit :

Hi,

if you are using Pharo7, you could do either on a class (affects all instances) or on an object (affects only the target instance):

classOrObject link: yourMetaLink toSlotNamed: #slotName option: #write

It will install the metalink on all write accesses to the slot.

Note that if you target a single object, it will be migrated to an anonymous subclass for the metalink to be object-specific.

 

In both cases, if you add or remove inst-var accesses, the metalink should update automatically.

 

Steven.

 

 

Le 2019-04-03 15:57, Vitor Medina Cruz a écrit :

Hello,

Is it possible to intercept a slot store? I tried with a before metalink into #write:to selector, but it don't seems to work. Should I use another selector?

I would like to experiment with ivar change notification, but I don't know what is the better approach. I know I could install a MetaLink in an attribution node, but that seems ankward and I would have to edit the linkage every time my object is changed, isn't true?

Regards,
Vitor

 

 

Reply | Threaded
Open this post in threaded view
|

Re: Slots and Metalink

Marcus Denker-4
In reply to this post by Vitor Medina Cruz


> On 3 Apr 2019, at 15:57, Vitor Medina Cruz <[hidden email]> wrote:
>
> Hello,
>
> Is it possible to intercept a slot store? I tried with a before metalink into #write:to selector, but it don't seems to work. Should I use another selector?
>

The #write:to: method is the reflective read method that implements read on the level of the variable. If you subclass class Slot, you can make you own kind of
Variables by just overriding #write:to  and read:

But of course compiling every read by calling a method would be very slow.

Therefore, one can override emitStore: and emitValue: to instead emit faster code by telling the compiler exactly what bytecode to generate for read and write.
This makes it much faster, but at the expense that the reflective methods are not called anymore.

(It would be nicer if we would inline the read: code automatically, but that has its own set of problems)


> I would like to experiment with ivar change notification, but I don't know what is the better approach.
>

What you could do is to make your own subclass to experiment. IndexedSlot is the superclass of the normal instancevariables, but without the optimised code generation.
So it is the perfect superclass to experiment:

IndexedSlot subclass: #MyTestSlot
        instanceVariableNames: ''
        classVariableNames: ''
        package: 'Slot-Core-Variables’


now Implement

read: anObject
        Transcript show: 'reading ', self name.
        super read: anObject.


Now we can make a class that uses it:

Object subclass: #MyClass
        slots: { #ivar => MyTestSlot }
        classVariables: {  }
        package: 'Slot-Core-Variables’


and add a simple method reading the variable:

ivar
        ^ivar

If you now execute "MyClass new ivar” and you will see the output on the Transcript.


        Marcus
Reply | Threaded
Open this post in threaded view
|

Re: Slots and Metalink

Vitor Medina Cruz
Steven:

Oh! I was unaware of these methods under reflection protocol! I manage to make it work, and it is simply AWESOME!! :)

Marcus:

I wanted to intercept the store generally, with any kind of slot, kind of an AOP aproach. I did this:

| slotLink |

slotLink := (MetaLink new
        metaObject: [Transcript show: 'ihaaaa!!!!'];
        selector: #value;
        arguments: #();
        control: #before).
       


TestObject link: slotLink toSlotNamed: #b option: #write.


And it worked like a charm! By you explanation, this would lead to some performance penality, but it seems a really powerfull mechanism to me, and it's performance should be similar to that of extending a Slot, no?



On Thu, Apr 4, 2019 at 5:04 AM Marcus Denker <[hidden email]> wrote:


> On 3 Apr 2019, at 15:57, Vitor Medina Cruz <[hidden email]> wrote:
>
> Hello,
>
> Is it possible to intercept a slot store? I tried with a before metalink into #write:to selector, but it don't seems to work. Should I use another selector?
>

The #write:to: method is the reflective read method that implements read on the level of the variable. If you subclass class Slot, you can make you own kind of
Variables by just overriding #write:to  and read:

But of course compiling every read by calling a method would be very slow.

Therefore, one can override emitStore: and emitValue: to instead emit faster code by telling the compiler exactly what bytecode to generate for read and write.
This makes it much faster, but at the expense that the reflective methods are not called anymore.

(It would be nicer if we would inline the read: code automatically, but that has its own set of problems)


> I would like to experiment with ivar change notification, but I don't know what is the better approach.
>

What you could do is to make your own subclass to experiment. IndexedSlot is the superclass of the normal instancevariables, but without the optimised code generation.
So it is the perfect superclass to experiment:

IndexedSlot subclass: #MyTestSlot
        instanceVariableNames: ''
        classVariableNames: ''
        package: 'Slot-Core-Variables’


now Implement

read: anObject
        Transcript show: 'reading ', self name.
        super read: anObject.


Now we can make a class that uses it:

Object subclass: #MyClass
        slots: { #ivar => MyTestSlot }
        classVariables: {  }
        package: 'Slot-Core-Variables’


and add a simple method reading the variable:

ivar
        ^ivar

If you now execute "MyClass new ivar” and you will see the output on the Transcript.


        Marcus
Reply | Threaded
Open this post in threaded view
|

Re: Slots and Metalink

Marcus Denker-4


> On 4 Apr 2019, at 15:04, Vitor Medina Cruz <[hidden email]> wrote:
>
> Steven:
>
> Oh! I was unaware of these methods under reflection protocol! I manage to make it work, and it is simply AWESOME!! :)
>
> Marcus:
>
> I wanted to intercept the store generally, with any kind of slot, kind of an AOP aproach. I did this:
>
> | slotLink |
>
> slotLink := (MetaLink new
>         metaObject: [Transcript show: 'ihaaaa!!!!'];
>         selector: #value;
>         arguments: #();
>         control: #before).
>        
>
>
> TestObject link: slotLink toSlotNamed: #b option: #write.
>
>
> And it worked like a charm! By you explanation, this would lead to some performance penality, but it seems a really powerfull mechanism to me, and it's performance should be similar to that of extending a Slot, no?
>

From a bytecode perspective it is the same as if you would make a Slot *and* implement bytecode generation. (with the slight overhead of the block execution).

So yes, a nice solution.

In general, MetaLinks are nice if you want to do “magic” that are not supposed to be visible. Making a Slot subclass makes a change more explicit. Both have their value, depending on the situation.

        Marcus