NAME

destroy - object destruction method

SYNOPSIS

obj.destroy()

APPLIES TO

Objects about to be destroyed due to garbage collection.

ARGUMENTS

None

RETURN VALUE

None

DESCRIPTION

When a dynamically-created object is about to be destroyed due to garbage collection, if it has a destroy method, that method will be called before the object is completedly destroyed. An object that is pending final destruction is termed a zombie. All references to dynamic values in the object are replaced with nil, and the object is made read-only. However, if a new reference to the zombie object is created during execution of the destroy method, then the object is resurrected (but in the read-only state with its dynamic value references still changed to nil).

Although it is allowable to directly call an object's destroy method, it is not generally encouraged. It is a fatal error to attempt to call oadl::gc during destroy method processing.

EXAMPLES

          class cls {
             public proc destroy() {
                 "cls.destroy()\n";
             }
          }

          // Create a dynamici object
          a = new cls()

          // Remove all references to that object
          a = nil

          // Call garbage collection - the destroy method
          // will be called
          oadl::gc()
    cls.destroy()

        // Demonstrate zombie processing
        var z
        var resurrect = true

        class foo {
            public var a, b;
            public proc create(x) {
                a = @x; b = x;
                "foo.create - returning ", self, '\n';
            }
            public proc destroy() {
                "", self, ".destroy() {\n";
                "    self.readonly() = ", self.readonly(), '\n';
                "    oadl::deleted(self) = ", oadl::deleted(self), '\n';
                "    dynamic copy ", a, " vs static ref ", b, '\n';
                "}\n";
                if (resurrect) z = self;
            }
        }

        a = new foo("foo")
    foo.create - returning #OBJ(1)

        a = nil
        oadl::gc()
    #OBJ(1).destroy() {
        self.readonly() = true
        oadl::deleted(self) = true
        dynamic copy nil vs static ref foo
    }

        // Set z.b to a dynamic copy of the string - it will get deleted
        // next time around
        z.b = @z.b
        "Examining resurrected zombie ", z, '\n'
    Examining resurrected zombie #OBJ(1)

        "z.b = ", z.b, '\n'
    z.b = foo

        "oadl::deleted(z) = ", oadl::deleted(z), '\n'
    oadl::deleted(z) = false

        resurrect = false
        z = nil
        oadl::gc()
    #OBJ(1).destroy() {
        self.readonly() = true
        oadl::deleted(self) = true
        dynamic copy nil vs static ref nil
    }

    // Demonstrate illegal recursive GC
    class badGC {
        public proc destroy() { oadl::gc(); }
    }
    a = new badGC()
    a = nil
    oadl::gc()
Recursive GC

SEE ALSO

complete
create
deleted
readonly