On Sunday, January 29, 2017 at 1:04:35 AM UTC+8, Axel Wagner wrote:
>
> On Sat, Jan 28, 2017 at 4:05 PM, T L <tapi...@gmail.com <javascript:>> 
> 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.
>

Ok, good explanation (as well as the explanation of Konstantin Khomoutov).

So SetFinalizer is for lib maintainers to avoid lib users not doing things 
correctly, right?
This is not well emphasized in the API docs. 

 

>  
>
>>
>> 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...@googlegroups.com <javascript:>.
>> 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