On 29-Aug-09, at 7:38 AM, vasil wrote:
The question is: why GC does not collect unreferenced thread objects in first case and do collect them in second case?
Vasil
Gambit implements the concept of "thread groups" (which is an extension of SRFI 18 and 21). When a thread is created, by default it is put in the same thread group as the parent thread. It will stay in the thread group until it terminates. So if a thread is not started it will stay in the thread group of its parent. Because the parent thread in your example does not terminate (it is the primordial thread), the garbage collector does not reclaim the thread group (which would have reclaimed the threads that were not started).
For example:
% gsi Gambit v4.5.1
(thread-group->thread-list (thread-thread-group (current-thread)))
(#<thread #1 primordial>)
(define t (do ((i 0 (+ 1 i)) (l '() (cons (make-thread (lambda ()
(void))) l))) ((> i 5) l)))
(thread-group->thread-list (thread-thread-group (current-thread)))
(#<thread #1 primordial> #<thread #2> #<thread #3> #<thread #4> #<thread #5> #<thread #6> #<thread #7>)
(for-each thread-start! t) (thread-group->thread-list (thread-thread-group (current-thread)))
(#<thread #1 primordial>)
To get around this, you could create each thread in its own thread group:
% gsi Gambit v4.5.1
(gc-report-set! #t) (define t (do ((i 0 (+ 1 i)) (l '() (cons (make-thread (lambda ()
(void)) 'name1 (make-thread-group 'name2 #f)) l))) ((> i 10000) l))) *** GC: 1 ms, 348K alloc, 206K heap, 64.1K live (31% 43032+22620) *** GC: 1 ms, 488K alloc, 654K heap, 202K live (31% 184184+22620) *** GC: 2 ms, 937K alloc, 1.51M heap, 650K live (42% 642616+22620) *** GC: 6 ms, 1.79M alloc, 3.26M heap, 1.51M live (46% 1558648+22620) *** GC: 14 ms, 3.55M alloc, 6.76M heap, 3.26M live (48% 3394872+22620) *** GC: 21 ms, 7.05M alloc, 13.8M heap, 6.76M live (49% 7063160+22620)
(set! t #f) (##gc)
*** GC: 2 ms, 8.28M alloc, 206K heap, 43.7K live (21% 22096+22620)
Marc