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 <[email protected]> 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
<[email protected]>:

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 <[email protected]> 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 <[email protected]>:

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 <[email protected]> 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

Reply via email to