A Garbage Collection Exerciser

Ordinary objects are removed silently by LITTLE's garbage collector, as soon as there are no references left to them. Objects using ressources not under GC control, which desire to dispose those ressources when they get garbage collected, must extend the class little.lang.CustomResourceUser and override the method free (), which should be hidden and must be implemented carefully - keep in mind, that operations on native ressources can't be controlled by the VM and may cause a VM crash, if they run wild ...

This program repeatedly creates lists, fills them with values, which are partly subject of GC finalization, and throws them away. A correct implementation of LITTLE should run this program with constant memory demands.


(package test)

(using
        little.lang.CustomResourceUser
        little.lang.Exception
        little.lang.InstantiableObject
        little.io.TextInputStream
        little.io.TextOutputStream)

(class Thing (CustomResourceUser InstantiableObject)

        (attribute
                freed
                id
                id:static
                sym)

        (method init () :static
                (set self:id 0))

        (method id () :static
                (set self:id (self:id:succ)))

        (method init (sym)
                (set self:sym sym)
                (set self:id (Thing:id))
                self)

        (method tostring ()
                (self:sym:tostring))

        (method free ()
                (if
                        self:freed
                        (prog
                                ((TextOutputStream:err):println 'Thing self:id 'freed 'twice)
                                ((Exception:new 'FreedTwice):throw))
                        (prog
                                ((TextOutputStream:out):println 'Thing self:id 'freed)
                                (set self:freed true))))

)

(class ListTester (little.lang.InstantiableObject)

        (attribute
                list)

        (method init ()
                (set self:list (little.lang.container.LinkedList:new))
                (self:list:put (Thing:new 'Hello))
                (self:list:put 'World)
                (self:list:put 'this)
                (self:list:put 'is)
                (self:list:put 'a)
                (self:list:put 'Test)
                (self:list:put 'lez)
                (self:list:put 'see)
                (self:list:put 'more)
                (self:list:put 'of)
                (self:list:put 'it)
                self)

        (method reverse ()
                (self:list:reverse))


        (method go (n) :static
                (let ((me nil) (i 0) (j 0))
                        (while (j:lt n)
                                (set i 0)
                                (set me (self:new))
                                (while (i:lt 100)
                                        ((TextOutputStream:out):println i ":" (me:reverse))
                                        (me:reverse)
                                        (set i (i:succ)))
                                (set j (j:succ)))))

        (method main () :static
                (let ((n (((System:arguments):nextElement):toint)))
                        true
                        (try
                                (self:go n)
                                (return nil)
                         catch (e)
                               (cond
                                        (((e:id):equals 'ExceptionInFree)
                                                ((TextOutputStream:out):println (e:id))
                                                (return 0))
                                        (((e:id):equals 'ExceptionInClassInit)
                                                ((TextOutputStream:out):println "Exception caught:" (e:id))
                                                (return 0))
                                        (((e:id):equals 'Interrupt)
                                                ((TextOutputStream:out):println "Interrupted.")
                                                ((TextOutputStream:out):println "Do you want to resume (y/n)?")
                                                (if (((TextInputStream:in):readChar):equals "y"c)
                                                        ((TextInputStream:in):readChar)
                                                        (return nil)))
                                        (true nil))))
                nil)

  )