// exportPtr returns *permPtrMsg if importer is nil, and *ptrMsg otherwise. func (r *Runtime) exportPtr(v interface{}, importer n.Addr) interface{} { // Add exported value to export table exph := r.exp.Add(v, importer) // log.Printf("exporting %T with handle %s for importer %v", v, exph.ID.String(), importer) if importer == nil { return &permPtrMsg{ID: exph.ID, TypeID: exph.Type.ID} } // Monitor the importer for liveness. // DropPtr the handles upon importer death. r.lk.Lock() defer r.lk.Unlock() _, ok := r.live[importer.WorkerID()] if !ok { r.live[importer.WorkerID()] = struct{}{} // The anonymous function creates a "lifeline" connection to the worker importing v. // When this conncetion is broken, v is released. go func() { // Defer removal of v's handle from the export table to the end of this function defer func() { r.lk.Lock() delete(r.live, importer.WorkerID()) r.lk.Unlock() // DropPtr/forget all exported handles r.exp.RemoveImporter(importer) }() conn, err := r.t.Dial(importer) if err != nil { // log.Println("problem dialing lifeline to", importer.String(), err.Error()) return } defer conn.Close() if conn.Write(&dontReplyMsg{}) != nil { log.Println("problem writing on lifeline to", importer.String(), err.Error()) return } // Read returns when the remote dies and // runs the conn into an error conn.Read() }() } return &ptrMsg{ID: exph.ID, TypeID: exph.Type.ID} }