On Sat, Jan 28, 2017 at 4:05 PM, T L <tapir....@gmail.com> wrote:

>
>
> On Saturday, January 28, 2017 at 10:46:50 PM UTC+8, Dave Cheney wrote:
>>
>>
>>
>> On Sunday, 29 January 2017 01:42:08 UTC+11, T L wrote:
>>>
>>>
>>>
>>> On Saturday, January 28, 2017 at 10:33:08 PM UTC+8, Dave Cheney wrote:
>>>>
>>>>
>>>>
>>>> On Sunday, 29 January 2017 01:25:20 UTC+11, T L wrote:
>>>>>
>>>>>
>>>>>
>>>>> On Saturday, January 28, 2017 at 9:33:51 PM UTC+8, C Banning wrote:
>>>>>>
>>>>>> From the doc: "The finalizer for obj is scheduled to run at some
>>>>>> arbitrary time after obj becomes unreachable. There is no guarantee that
>>>>>> finalizers will run before a program exits, so typically they are useful
>>>>>> only for releasing non-memory resources associated with an object during 
>>>>>> a
>>>>>> long-running program."
>>>>>>
>>>>>
>>>>>
>>>>> If this is true, then the SetFinalizer function would be much
>>>>> meaningless.
>>>>>
>>>>
>>>> Yes. The only reasonable way to interpret the operation of SetFinalizer
>>>> is to assume it does not thing and program accordingly.
>>>>
>>>> To repeat, you cannot base the correct operation of your program on a
>>>> finaliser running before your program exits.
>>>>
>>>
>>> I know, I just want to make sure some fanalizers will get executed for a
>>> long running program.
>>>
>>
>> Finalisers are not guaranteed to run, no matter how long the program runs
>> for, no matter how important they are.
>>
>>
>>> But it looks the current implementation of SetFinalizer can't make any
>>> guarantee at all.
>>>
>>
>> Correct. Finalisers are not guaranteed to run. You should not base the
>> correct operation of your program on a finaliser running before your
>> program exits.
>>
>
> My understanding is finalisers are guaranteed to run for some cases, but
> not for some other cases, for a long running program.
>

Your understanding is false. They are not guaranteed to run, fullstop.


> If any cases are not guaranteed to run, then SetFinalizer would be totally
> useless.
>

See Konstantin's Post. They are not totally useless and their uses are
documented (though I'd rephrase it as "resources that are not go-allocated
memory"). You can not rely on them for correctness, but you *can* use them
as an additional defense against some kind of bugs, like unclosed files.
You can use them to do any kind of work that a) helps a long-running
program not crash and b) is not necessary to do if your process dies.
Examples are

* freeing C-allocated memory (the OS will cleanup after you, but a
long-running program will crash, if it accidentally doesn't free the memory
manually)
* Closing files (the OS will automatically close all files when your
process exits, but a long-running program might run out of FDs and crash if
it accidentally doesn't close the files)
* Munmap a memory region (the OS will unmap the files anyway when you exit,
but…)

In all of these cases, your program doesn't *rely* on the Finalizer to run,
for correctness, but it will be helped by it, in the presence of bugs. But
a Finalizer is not a Destructor and that's also a *good* thing. Consider
C++, where most of the work of Destructors is 100% unnecessary when the
process exits, but is still done; now your program exiting/restarting is
unnecessarily slowed down by doing work that the kernel can do more
efficiently for you.


>
> BTW, more study:
>
> package main
>
> import "time"
> import "runtime"
>
> type E int8
> const N=2
>
> type T [N]E
>
> func main() {
>     for i := range [8]struct{}{} {
>         t := &T{0:E(i)}
>         runtime.SetFinalizer(t, func(p *T) {print((*p)[0])})
>     }
>     runtime.GC()
>     time.Sleep(time.Second * 1)
> }
>
> output:
> .......E..........output(N=1)..........output(N=2)
> .......int8....... ....................7654
> .......int16......7654.................765432
> .......int32......765432...............7654321
> .......int64......7654321..............76543210
>
>
>
>
>>
>>>
>>>
>>>>
>>>>> BTW, it looks both finalizer will get executed if let the program
>>>>> sleep more than 10us at the beginning:
>>>>>
>>>>> package main
>>>>>
>>>>> import "time"
>>>>> import "runtime"
>>>>>
>>>>> func main() {
>>>>>         time.Sleep(10 * time.Microsecond)
>>>>>         // if sleep 10 Microsecond here, 2 and 1 will both be out
>>>>>         // if sleep 1 Microsecond here, still only 2 will out
>>>>>
>>>>>         t1 := new(int)
>>>>>         t2 := new(int)
>>>>>
>>>>>         runtime.SetFinalizer(t1, func(*int) {println(1)})
>>>>>         runtime.SetFinalizer(t2, func(*int) {println(2)})
>>>>>      runtime.GC()
>>>>>         time.Sleep(time.Second * 20)
>>>>> }
>>>>>
>>>>>
>>>>>>
>>>>>>
>>>>>> On Saturday, January 28, 2017 at 6:17:37 AM UTC-7, T L wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> package main
>>>>>>>
>>>>>>> import "time"
>>>>>>> import "runtime"
>>>>>>>
>>>>>>> type T1 struct{ i int }
>>>>>>> type T2 struct{ i int }
>>>>>>>
>>>>>>> func main() {
>>>>>>>         t1 := new(T1)
>>>>>>>         t2 := new(T2)
>>>>>>>
>>>>>>>         runtime.SetFinalizer(t1, func(*T1) {println(1)})
>>>>>>>         runtime.SetFinalizer(t2, func(*T2) {println(2)})
>>>>>>>         runtime.GC()
>>>>>>>         time.Sleep(time.Second * 2)
>>>>>>>
>>>>>>>         // the program will output: 2
>>>>>>>         // if I adjust the order of the declarations of t1 and t2,
>>>>>>>         // the program will output: 1
>>>>>>> }
>>>>>>>
>>>>>>> Why the finalizer for the first declaration will not get called?
>>>>>>>
>>>>>> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to