Loading ...
Sorry, an error occurred while loading the content.

object finalization

Expand Messages
  • Florent Monnier
    Hi, I would like that a method of an object to be called when this object is finalized. Is it possible ? -- thanks
    Message 1 of 7 , May 1, 2006
    • 0 Attachment
      Hi,

      I would like that a method of an object to be called when this object is
      finalized. Is it possible ?

      --
      thanks
    • Richard Jones
      ... I think the answer is _no_, because calling the method of an object assumes that you have a pointer to the object around, and if you have a pointer to the
      Message 2 of 7 , May 2, 2006
      • 0 Attachment
        On Tue, May 02, 2006 at 08:56:17AM +0200, Florent Monnier wrote:
        > I would like that a method of an object to be called when this object is
        > finalized. Is it possible ?

        I think the answer is _no_, because calling the method of an object
        assumes that you have a pointer to the object around, and if you have
        a pointer to the object around then the object can never become truly
        unreachable, so it is never finalised :-(

        Here is my test program. Note that the finaliser isn't called, and I
        assume it's because self#finaliser contains a pointer (self) to the
        object.

        #!/usr/bin/ocamlrun ocaml

        let () =
        let obj = object (self)
        method hello = prerr_endline "hello"
        method finaliser _ = prerr_endline "in finaliser"
        initializer
        prerr_endline "in initializer";
        Gc.finalise self#finaliser self
        end in

        obj#hello;

        (* cause the object to become unreachable *)
        let obj = () in

        (* call the garbage collector so the object should be finalised *)
        Gc.full_major ();

        prerr_endline "finished GC full major cycle"

        It might be best to ask about this on caml-list ...

        Rich.

        --
        Richard Jones, CTO Merjis Ltd.
        Merjis - web marketing and technology - http://merjis.com
        Team Notepad - intranets and extranets for business - http://team-notepad.com
      • Thierry Martinez
        ... I am discovering the Gc module thanks to your message. In the OCaml documentation, a warning says that the registered callback has to be out of the scope
        Message 3 of 7 , May 2, 2006
        • 0 Attachment
          Answering to the following Florent Monnier's question:
          >> I would like that a method of an object to be called when this object is
          >> finalized. Is it possible ?

          Richard Jones wrote:
          > let () =
          > let obj = object (self)
          > method hello = prerr_endline "hello"
          > method finaliser _ = prerr_endline "in finaliser"
          > initializer
          > prerr_endline "in initializer";
          > Gc.finalise self#finaliser self
          > end in

          I am discovering the Gc module thanks to your message. In the OCaml
          documentation, a warning says that the registered callback has to be
          out of the scope of the considered value, such that its closure
          doesn't capture the value. Your code could be rewritten as:

          let finaliser obj = obj#finaliser

          let obj = object (self)
          method hello = prerr_endline "hello"
          method finaliser _ = prerr_endline "in finaliser"
          initializer
          prerr_endline "in initializer";
          Gc.finalise finaliser self
          end

          That seems to work.

          --
          Thierry.
        • Richard Jones
          ... This is my revised version, but I still can t get it to run the finaliser ... #!/usr/bin/ocamlrun ocaml let finaliser obj = obj#finaliser let () = let obj
          Message 4 of 7 , May 2, 2006
          • 0 Attachment
            On Tue, May 02, 2006 at 11:11:55AM +0100, Thierry Martinez wrote:
            > Answering to the following Florent Monnier's question:
            > >> I would like that a method of an object to be called when this object is
            > >> finalized. Is it possible ?
            >
            > Richard Jones wrote:
            > > let () =
            > > let obj = object (self)
            > > method hello = prerr_endline "hello"
            > > method finaliser _ = prerr_endline "in finaliser"
            > > initializer
            > > prerr_endline "in initializer";
            > > Gc.finalise self#finaliser self
            > > end in
            >
            > I am discovering the Gc module thanks to your message. In the OCaml
            > documentation, a warning says that the registered callback has to be
            > out of the scope of the considered value, such that its closure
            > doesn't capture the value. Your code could be rewritten as:
            >
            > let finaliser obj = obj#finaliser
            >
            > let obj = object (self)
            > method hello = prerr_endline "hello"
            > method finaliser _ = prerr_endline "in finaliser"
            > initializer
            > prerr_endline "in initializer";
            > Gc.finalise finaliser self
            > end
            >
            > That seems to work.

            This is my revised version, but I still can't get it to run the
            finaliser ...

            #!/usr/bin/ocamlrun ocaml

            let finaliser obj = obj#finaliser

            let () =
            let obj = object (self)
            method hello = prerr_endline "hello"
            method finaliser = prerr_endline "in finaliser"
            initializer
            prerr_endline "in initializer";
            Gc.finalise finaliser self
            end in

            obj#hello;

            (* cause the object to become unreachable *)
            let obj = () in

            (* call the garbage collector so the object should be finalised *)
            Gc.full_major ();

            prerr_endline "finished GC full major cycle"

            Output:

            $ ./final.ml
            in initializer
            hello
            finished GC full major cycle

            Rich.

            --
            Richard Jones, CTO Merjis Ltd.
            Merjis - web marketing and technology - http://merjis.com
            Team Notepad - intranets and extranets for business - http://team-notepad.com
          • Thierry Martinez
            ... I believe the problem here is that the compiler doesn t notice your object is unreachable when you call Gc.full_major: it is a bit unclear for me, but
            Message 5 of 7 , May 2, 2006
            • 0 Attachment
              Richard Jones:
              > This is my revised version, but I still can't get it to run the
              > finaliser ...
              >
              > #!/usr/bin/ocamlrun ocaml
              >
              > let finaliser obj = obj#finaliser
              >
              > let () =
              > let obj = object (self)
              > method hello = prerr_endline "hello"
              > method finaliser = prerr_endline "in finaliser"
              > initializer
              > prerr_endline "in initializer";
              > Gc.finalise finaliser self
              > end in
              >
              > obj#hello;
              >
              > (* cause the object to become unreachable *)
              > let obj = () in
              >
              > (* call the garbage collector so the object should be finalised *)
              > Gc.full_major ();
              >
              > prerr_endline "finished GC full major cycle"

              I believe the problem here is that the compiler doesn't notice your
              object is unreachable when you call Gc.full_major: it is a bit unclear
              for me, but formaly you have two nested bindings of obj, and the
              compiler has no clue that your first binding will no longer be used
              since it still is in the scope (it is just masked by a mere notation
              choice, but in my opinion, your two identifiers' having the same name
              here is just relevant at a syntactic level and is not considered by
              Gc[#]). You could indeed have something like, where it is clear that
              the first "obj" is still reachable, whereas the scope is in the same
              shape than in your code:

              let () =
              let obj = object (self)
              ...
              end in

              obj#hello;
              (
              (* cause the object to become unreachable *)
              let obj = () in

              (* call the garbage collector so the object should be finalised *)
              Gc.full_major ();
              );
              obj#hello;

              In my opinion, here is a possibly way to force the unreachability:

              let () =
              begin
              let obj = object (self)
              ...
              end

              obj#hello;
              end
              Gc.full_major ()

              --
              Thierry.

              [#] It is very unclear for me, because it seems that a top-level
              binding of an identifier with the same name of a previously bound
              one masks the latter.
            • Remi Vanicat
              ... Exactly. More precisely, when you compare let bla = new foo in let bla = () in bar baz to let bla = new foo in bar baz then if you bytecompile it, it is
              Message 6 of 7 , May 2, 2006
              • 0 Attachment
                2006/5/2, Thierry Martinez <thierry.martinez@...>:
                > Richard Jones:
                > > This is my revised version, but I still can't get it to run the
                > > finaliser ...
                > >
                > > #!/usr/bin/ocamlrun ocaml
                > >
                > > let finaliser obj = obj#finaliser
                > >
                > > let () =
                > > let obj = object (self)
                > > method hello = prerr_endline "hello"
                > > method finaliser = prerr_endline "in finaliser"
                > > initializer
                > > prerr_endline "in initializer";
                > > Gc.finalise finaliser self
                > > end in
                > >
                > > obj#hello;
                > >
                > > (* cause the object to become unreachable *)
                > > let obj = () in
                > >
                > > (* call the garbage collector so the object should be finalised *)
                > > Gc.full_major ();
                > >
                > > prerr_endline "finished GC full major cycle"
                >
                > I believe the problem here is that the compiler doesn't notice your
                > object is unreachable when you call Gc.full_major: it is a bit unclear
                > for me, but formaly you have two nested bindings of obj, and the
                > compiler has no clue that your first binding will no longer be used
                > since it still is in the scope

                Exactly. More precisely, when you compare

                let bla = new foo in
                let bla = () in
                bar baz

                to
                let bla = new foo in
                bar baz

                then if you bytecompile it, it is mostly the same as the byte compiler
                does not give back the biding to the GC before the biding is ended.
                If you native compile it, it is mostly the same because ocamlopt to
                optimization to give back the biding whenever it is not needed anymore
                (here it is just after it have been declared).

                So one way or another the "let bla = () in" binding can only serve as
                a documentation programing (we don't need the old binding anymore) or
                as a protective way (we can't use the old binding anymore), but
                neither compiler use it for GC.
              • Richard Jones
                A version which works: let finaliser obj = obj#finaliser;; begin let obj = object (self) method hello = prerr_endline hello method finaliser = prerr_endline
                Message 7 of 7 , May 2, 2006
                • 0 Attachment
                  A version which works:

                  let finaliser obj = obj#finaliser;;

                  begin
                  let obj = object (self)
                  method hello = prerr_endline "hello"
                  method finaliser = prerr_endline "in finaliser"
                  initializer
                  prerr_endline "in initializer";
                  Gc.finalise finaliser self
                  end in
                  obj#hello
                  end;;

                  (* the object has become unreachable *)

                  (* call the garbage collector so the object should be finalised *)
                  Gc.full_major ();;

                  prerr_endline "finished GC full major cycle"

                  $ ./final
                  in initializer
                  hello
                  in finaliser
                  finished GC full major cycle

                  Rich.

                  --
                  Richard Jones, CTO Merjis Ltd.
                  Merjis - web marketing and technology - http://merjis.com
                  Team Notepad - intranets and extranets for business - http://team-notepad.com
                Your message has been successfully submitted and would be delivered to recipients shortly.