From: cross@spitfire.i.gajendra.net   
      
   In article <10gvqg1$1stts$2@dont-email.me>,   
   Arne Vajhøj wrote:   
   >On 12/5/2025 12:15 PM, Dan Cross wrote:   
   >> In article <69320352$0$673$14726298@news.sunsite.dk>,   
   >> Arne Vajhøj wrote:   
   >>> Insert:   
   >>>   
   >>> cma_thread_detach(&t);   
   >>>   
   >>> and memory gets freed.   
   >>>   
   >>> I don't know if this is intentional.   
   >>   
   >> It appears so. From the extant documentation I could find about   
   >> CMA threads, in the description of, `cma_thread_create`:   
   >>   
   >> |The thread object exists until the cma_thread_detach routine is   
   >> |called **and** the thread terminates, whichever occurs last.   
   >>   
   >> [Emphasis added; note the "and" there.]   
   >   
   >So it is documented, which obviously make it intentional.   
      
   That's my read of it.   
      
   >>> Usually join is sufficient.   
   >   
   >First a correction of myself.   
   >   
   >join is sufficient for GC languages.   
   >   
   >For non-GC languages join + destructor is sufficient.   
      
   Well, it depends on your definition of "sufficient."   
      
   I took you to mean, "to reclaim the resources used by the thread   
   library." Obviously other program-managed data falls outside of   
   the realm of what should be done by the library when joining a   
   thread; if one allocated a heap object and did not free it when   
   the thread terminated and was joined, that would be a leak in a   
   language without automatic memory management.   
      
   >But nobody is surprised that their C++ code is leaking   
   >memory if they forget:   
   > delete t;   
      
   Of course. That seems orthogonal to what the thread library   
   would do, however. Given your minimal example, where the   
   program did no direct allocation of memory, it seemed logical   
   that the error must be in how the interface was used.   
      
   >> With pthreads, yes. Evidently not with CMA.   
   >   
   >It is a weird usage if we look at what a thread_detach   
   >function does.   
   >   
   >function thread_detach() {   
   > // test inserted in V1.1 to handle cases where the thread completed   
   >before this function got called   
   > if(thread is terminated) {   
   > call thread_free()   
   > return   
   > }   
   > // change state   
   > state = detached // any attempts to join will now fail   
   > // setup free at termination   
   > on_termination_handler = function {   
   > call thread_free()   
   > }   
   >}   
   >   
   >Calling this function after a join that ensures thread   
   >is terminated will obviously free.   
   >   
   >But why not expose the thread_free function?   
      
   Presumably because someone might call it on a still-running   
   thread by accident. It's unclear what the semantics _should_   
   be.   
      
   But I'm speculating.   
      
   >Or let thread_join call thread_free, because thread_join   
   >knows that the thread is terminated before it completes.   
      
   It seems that the POSIX committee that created pthreads asked   
   the same questions and decided there was no good reason for   
   thread join _not_ to free the resources in question.   
      
   If I were to hazard a guess, CMA requires both steps in order to   
   work around a race condition of some kind. I see in the CMA   
   documentation that multiple threads may join on a given thread;   
   all are unblocked when the thread terminates. This is, again,   
   unlike pthreads, where only one thread my join on a thread. The   
   two-step mechanism for freeing might have been mean to give CMA   
   threads a way to coordinate multiple joiners, where the last one   
   to reference the thread detachs it, thus freeing the resources.   
      
   But again, I'm speculating.   
      
    - Dan C.   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|