Updated 2011-06-21 02:06:41 by RLE

Name: freeMem

Description: Spawn a Tcl interpreter using a Tcl pipe, evaluate some code, and get all the memory back.

Parameters: code - arbitrary tcl code

Usage:
        set mid [ freeMem { puts foo! } ]
        vwait $mid   ;## since we are waiting on the KEY.
        (when you are through do "unset $mid")
   or
        set mid [ freeMem "return foo!" ]
        vwait $mid
        set retval [ eval [ set $mid ] ]
        unset $mid

Comments: This is slow due to the initialization overhead, but is convenient if you have a long running process that occasionally needs to do something that is memory intensive and would otherwise cause all the memory on the machine to wind up on the heap of the current process.

If the code being evaluated here needs to do anything in the caller's scope the value returned by freeMem should be eval'd by the caller. Otherwise it is just set to dereference it.
 proc freeMem { code } {
     
     set uniqueid [ clock clicks -milliseconds ]
     
     set ::$uniqueid [ list ]
        
     ;## internal callback
     proc __freeMem__ { fid uniqueid } {
          if { [ catch {
             set ::$uniqueid [ read $fid ]
             close $fid
          } err ] } { 
             return -code error $err
          }
     }
     
     ;## handle return values (including return -codes)
     regsub -all {return .+} $code "puts {&}" code
     
     if { [ catch {
        set fid [ open |tclsh w+ ]
        fconfigure $fid -blocking off
        fconfigure $fid -buffering line
        puts $fid $code             
        fileevent $fid readable "__freeMem__ $fid $uniqueid"
     } err ] } {
        catch { close $fid }
        return -code error $err
     }
     return ::$uniqueid       
 }

--Phil Ehrens