Replacing a single function/method in an existing live class?

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

Replacing a single function/method in an existing live class?

Stephen R. van den Berg
Say I have this:

class A {
  int k;
  void B() {
    write("foo %d\n", k);
  }
  void C() {
    k = 3;
    write("bar\n");
  }
}

int main() {
  A a = A();
  a->C(); // Displays: bar
  a->B(); // Displays: foo 3
  // At this point I want to replace the function B
  // in the running/compiled instance of A in a.
  //  I.e. I want to call compile() or similar
  //  on the following code:
  //    void B() { write("FOO %d\n", k); }
  //  such that I can subsequently run:
  a->B();      // Should display: FOO 3
  return 0;
}

Any way this can be accomplished?
An alternate way would be to compile the whole class of A again, but
then run method B() in it with a custom this argument pointing to the
old instance in a.  Is that possible?  I know javascript can do this,
but it seems like Pike does not allow/support it.
--
Stephen.
Reply | Threaded
Open this post in threaded view
|

Re: Replacing a single function/method in an existing live class?

Chris Angelico
On Mon, May 3, 2021 at 2:04 AM Stephen R. van den Berg <[hidden email]> wrote:

>
> Say I have this:
>
> class A {
>   int k;
>   void B() {
>     write("foo %d\n", k);
>   }
>   void C() {
>     k = 3;
>     write("bar\n");
>   }
> }
>
> int main() {
>   A a = A();
>   a->C();       // Displays: bar
>   a->B();       // Displays: foo 3
>   // At this point I want to replace the function B
>   // in the running/compiled instance of A in a.
>   //  I.e. I want to call compile() or similar
>   //  on the following code:
>   //    void B() { write("FOO %d\n", k); }
>   //  such that I can subsequently run:
>   a->B();      // Should display: FOO 3
>   return 0;
> }
>
> Any way this can be accomplished?
> An alternate way would be to compile the whole class of A again, but
> then run method B() in it with a custom this argument pointing to the
> old instance in a.  Is that possible?  I know javascript can do this,
> but it seems like Pike does not allow/support it.

JavaScript has some utterly bizarre rules about the 'this' reference
that I wouldn't want to see any other language replicate. In Pike, a
function remembers the context it was created in, so what you're
trying to do won't work with injection. But perhaps subclassing can do
what you want - instead of compiling the entire class again, create a
subclass that replaces that one function.

ChrisA
Reply | Threaded
Open this post in threaded view
|

Re: Replacing a single function/method in an existing live class?

Stephen R. van den Berg
Chris Angelico wrote:
>trying to do won't work with injection. But perhaps subclassing can do
>what you want - instead of compiling the entire class again, create a
>subclass that replaces that one function.

Yes, well, that won't cut it, I'm afraid, because I specifically want
that function to be able to pretend that he is living inside the
already live/running older object of the old class (needs access to
those variables/members).

I'm trying to see how close I can get to rapid development where you
actually replace methods inside live classes during runtime.

On a related question then, if I do this:

class D {
  class E {
    void F() {
    }
  }
  function G() {
    E e = E();
    return e->F;
  }
}

int main() {
  D d = D();
  function ref = d->G();
  d = 0;
  gc();
  // At this point, does object d still
  // have references?
  // Or is it gone because from F
  // we do not refrence D?
  return 0;
}
--
Stephen.
Reply | Threaded
Open this post in threaded view
|

Re: Replacing a single function/method in an existing live class?

Lance Dillon-2
The closest I could see is to not really have the functions directly, I guess, but an mapping of functions, and overload `() so that it pulls the function from the mapping, then you could easily replace the function by replacing the reference in the mapping.

The replaced function would be locator collected,or you could implement it as a list of hooks.

Could be transparent to calling code and be effectively the same thing, even if implemented differently.

Unless I am misunderstanding how `() works.



On Sun, May 2, 2021 at 12:32 PM, Stephen R. van den Berg
Chris Angelico wrote:
>trying to do won't work with injection. But perhaps subclassing can do
>what you want - instead of compiling the entire class again, create a
>subclass that replaces that one function.

Yes, well, that won't cut it, I'm afraid, because I specifically want
that function to be able to pretend that he is living inside the
already live/running older object of the old class (needs access to
those variables/members).

I'm trying to see how close I can get to rapid development where you
actually replace methods inside live classes during runtime.

On a related question then, if I do this:

class D {
  class E {
    void F() {
    }
  }
  function G() {
    E e = E();
    return e->F;
  }
}

int main() {
  D d = D();
  function ref = d->G();
  d = 0;
  gc();
  // At this point, does object d still
  // have references?
  // Or is it gone because from F
  // we do not refrence D?
  return 0;

}
--
Stephen.
Reply | Threaded
Open this post in threaded view
|

Re: Replacing a single function/method in an existing live class?

Stephen R. van den Berg
Lance Dillon wrote:
>The closest I could see is to not really have the functions directly, I guess, but an mapping of functions, and overload `() so that it pulls the function from the mapping, then you could easily replace the function by replacing the reference in the mapping.
>The replaced function would be locator collected,or you could implement it as a list of hooks.
>Could be transparent to calling code and be effectively the same thing, even if implemented differently.
>Unless I am misunderstanding how `() works.

I think that method breaks at the point where you need to manipulate "this"
to point to the main class.

Ah well, I am restructuring the code so that the live class in question
is being referenced through a variable.  It seems that is the only
practical solution.
--
Stephen.
Reply | Threaded
Open this post in threaded view
|

Re: Replacing a single function/method in an existing live class?

Chris Angelico
On Mon, May 3, 2021 at 3:35 AM Stephen R. van den Berg <[hidden email]> wrote:

>
> Lance Dillon wrote:
> >The closest I could see is to not really have the functions directly, I guess, but an mapping of functions, and overload `() so that it pulls the function from the mapping, then you could easily replace the function by replacing the reference in the mapping.
> >The replaced function would be locator collected,or you could implement it as a list of hooks.
> >Could be transparent to calling code and be effectively the same thing, even if implemented differently.
> >Unless I am misunderstanding how `() works.
>
> I think that method breaks at the point where you need to manipulate "this"
> to point to the main class.
>
> Ah well, I am restructuring the code so that the live class in question
> is being referenced through a variable.  It seems that is the only
> practical solution.

My usual practice is to completely recompile the class, and have a
single mapping for all "carry-over" state, something like this:

class A {
    mapping s = ([]);
    void B() {...}
    void C() {...}
}

And then to replace anything, I'd create a new instance of the
newly-compiled class, replace its empty state mapping with the same
one as the old object, and start using that. It's simple, reliable,
and safe (if any old code is still referenced, it'll use the same
state mapping), and doesn't require weird shenanigans.

It might be kinda nice to have some sort of compiler support for
changing the 'this' context of a function, but it's really not
something that I'd use very often.

ChrisA
Reply | Threaded
Open this post in threaded view
|

Re: Replacing a single function/method in an existing live class?

Stephen R. van den Berg
Chris Angelico wrote:
>My usual practice is to completely recompile the class, and have a
>single mapping for all "carry-over" state, something like this:

>And then to replace anything, I'd create a new instance of the
>newly-compiled class, replace its empty state mapping with the same
>one as the old object, and start using that. It's simple, reliable,

Yes, if the class in completely in the source you control, that is fine.
But in this case the class comes from a sort-of library (from which
I inherit), and there is more state information than just the config, like:

- Caches.
- Database connection pools.
- Active sockets.
- Active sessions.
- Various call_out timers still pending.
- Statistics.

--
Stephen.
Reply | Threaded
Open this post in threaded view
|

Re: Replacing a single function/method in an existing live class?

Chris Angelico
On Mon, May 3, 2021 at 4:25 AM Stephen R. van den Berg <[hidden email]> wrote:

>
> Chris Angelico wrote:
> >My usual practice is to completely recompile the class, and have a
> >single mapping for all "carry-over" state, something like this:
>
> >And then to replace anything, I'd create a new instance of the
> >newly-compiled class, replace its empty state mapping with the same
> >one as the old object, and start using that. It's simple, reliable,
>
> Yes, if the class in completely in the source you control, that is fine.
> But in this case the class comes from a sort-of library (from which
> I inherit), and there is more state information than just the config, like:
>
> - Caches.
> - Database connection pools.
> - Active sockets.
> - Active sessions.
> - Various call_out timers still pending.
> - Statistics.
>

Ah, that does make it more complicated. Particularly with call_outs.

I don't think there's an easy way to do this.

ChrisA