[racket] Destructors in Racket

From: Evgeny Odegov (oev-racket at sibmail.com)
Date: Sat Aug 2 14:05:50 EDT 2014

Well, it turns out that objects like #(1 2 3) or '(1 2 3)
are not collected (optimizations?), but (vector 1 2 3) and
(list 1 2 3) are collected normally. It so happens that I tried #(1 2 3)
and '(1 2 3) first and came to the wrong conclusions :)



>   > But in case of another kind of value
>
> What another kiind? Small numbers and some chars are not garbage collected.
>
>
> Sat, 02 Aug 2014 22:47:32 +0700 от Evgeny Odegov <oev-racket at sibmail.com>:
>> In the example, the value is box and triggering occurs almost
>> immediately after set!.
>> But in case of another kind of value, triggering doesn't occur or take
>> much longer.
>> Why? (Or maybe I do something wrong?)
>>
>>> Probably you want to do something like this, I guess. It creates a
>>> single thread that just waits until anything registered with
>>> an-executor is garbage and then runs the executors. They will run
>>> asynchronously, but perhaps that's okay for your usecase.
>>>
>>> Robby
>>>
>>> #lang racket
>>> (define an-executor (make-will-executor))
>>> (void
>>>    (thread
>>>     (λ ()
>>>       (let loop ()
>>>         (will-execute an-executor)
>>>         (loop)))))
>>>
>>> (define a-box (box #f))
>>> (will-register an-executor
>>>                  a-box
>>>                  (λ (x) (printf "a-box is now garbage\n")))
>>> (collect-garbage) (collect-garbage) (collect-garbage)
>>> (printf "breaking the link\n")
>>> (set! a-box #f)
>>> (collect-garbage) (collect-garbage) (collect-garbage)
>>>
>>> On Sat, Aug 2, 2014 at 7:31 AM, Roman Klochkov < kalimehtar at mail.ru > wrote:
>>>> So I can write
>>>>
>>>> (define (make-obj stream)
>>>>      (define res  (obj (open-output-file "out.dat")))
>>>>      (define will (make-will-executor))
>>>>      (will-register will res (lambda (x) (close-output-port (obj-file x))))
>>>>      (thread (lambda () (let loop () (will-try-execute will) (sleep 1)
>>>> (loop)))))
>>>>
>>>> to make my objects? Additional threads don't hinder performance, do they?
>>>>
>>>> Or should I somehow figure out if the thread is already running, don't run
>>>> it and use common `will' for all objects?
>>>>
>>>> Sat, 2 Aug 2014 07:00:04 -0500 от Robby Findler
>>>> < robby at eecs.northwestern.edu >:
>>>>
>>>> One way is to set up a separate thread to do that.
>>>>
>>>> The reason they are not called automatically is sometimes running the
>>>> procedure passed to will-register needs to access some shared state
>>>> and so your program must be allowed to be in control of the timing of
>>>> the executor.
>>>>
>>>> In this case, it sounds like you can run the executor at any time, so
>>>> just creating a thread to close the port inside my-obj should work
>>>> fine.
>>>>
>>>> Robby
>>>>
>>>>
>>>> On Sat, Aug 2, 2014 at 6:15 AM, Roman Klochkov < kalimehtar at mail.ru > wrote:
>>>>> Then how?
>>>>>
>>>>> Suppose I have
>>>>> (struct obj (file))
>>>>> (define my-obj (obj (open-output-file "out.dat")))
>>>>>
>>>>> What I have to write to close the file, when my-obj will be GC'ed?
>>>>>
>>>>> I can write
>>>>> (define will (make-will-executor))
>>>>> (will-register will my-obj (lambda (x) (close-output-port (obj-file x))))
>>>>>
>>>>> But as far as I understand, it will not be called until `will-execute' or
>>>>> `will-try-execute' will be manually called?
>>>>>
>>>>> Then how to call will-try-execute when GC is collecting my-obj?
>>>>>
>>>>>
>>>>> Sat, 2 Aug 2014 11:57:32 +0100 от Matthew Flatt < mflatt at cs.utah.edu >:
>>>>>
>>>>> No, use the safe "will executors" API, instead.
>>>>>
>>>>> The unsafe finalizer API is for low-level, atomic finalization. Closing a
>>>>> port can flush buffers and more, and it's not a good idea to do that in an
>>>>> unsafe atomic context.
>>>>>
>>>>>> On Aug 2, 2014, at 11:12 AM, Roman Klochkov < kalimehtar at mail.ru > wrote:
>>>>>>
>>>>>> I have a structure, that has a filestream inside it. File have to be
>>>>>> cosed, when the structure is not used anymore (so gargbage collected).
>>>>>>
>>>>>> Is the best way to do
>>>>>> (require ffi/unsafe)
>>>>>> (register-finalizer my-obj
>>>>>> (lambda (x) (close-output-port (obj-file x))))
>>>>>>
>>>>>> ?
>>>>>>
>>>>>> It seems doing right thing, but why `ffi/unsafe'? Is it OK, when my
>>>>>> program actually doesn't use FFI?
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Roman Klochkov
>>>>>> ____________________
>>>>>> Racket Users list:
>>>>>>   http://lists.racket-lang.org/users
>>>>>
>>>>> --
>>>>> Roman Klochkov
>>>>>
>>>>> ____________________
>>>>> Racket Users list:
>>>>>   http://lists.racket-lang.org/users
>>>>>
>>>>
>>>> --
>>>> Roman Klochkov
>>> ____________________
>>>     Racket Users list:
>>>   http://lists.racket-lang.org/users
>> ____________________
>>    Racket Users list:
>>     http://lists.racket-lang.org/users
>>
>


Posted on the users mailing list.