toInsert *T // Keep this around to keep it alive.
toInsertWeak weak.Pointer[T]
)
- newValue := func() weak.Pointer[T] {
+ newValue := func() (T, weak.Pointer[T]) {
if toInsert == nil {
toInsert = new(T)
*toInsert = clone(value, &m.cloneSeq)
toInsertWeak = weak.Make(toInsert)
}
- return toInsertWeak
+ return *toInsert, toInsertWeak
}
var ptr *T
for {
wp, ok := m.Load(value)
if !ok {
// Try to insert a new value into the map.
- wp, _ = m.LoadOrStore(value, newValue())
+ k, v := newValue()
+ wp, _ = m.LoadOrStore(k, v)
}
// Now that we're sure there's a value in the map, let's
// try to get the pointer we need out of it.
"internal/abi"
"reflect"
"runtime"
+ "strings"
"testing"
+ "time"
+ "unsafe"
)
// Set up special types. Because the internal maps are sharded by type,
}
t.Errorf("failed to drain internal maps of %v", value)
}
+
+func TestMakeClonesStrings(t *testing.T) {
+ s := strings.Clone("abcdefghijklmnopqrstuvwxyz") // N.B. Must be big enough to not be tiny-allocated.
+ ran := make(chan bool)
+ runtime.SetFinalizer(unsafe.StringData(s), func(_ *byte) {
+ ran <- true
+ })
+ h := Make(s)
+
+ // Clean up s (hopefully) and run the finalizer.
+ runtime.GC()
+
+ select {
+ case <-time.After(1 * time.Second):
+ t.Fatal("string was improperly retained")
+ case <-ran:
+ }
+ runtime.KeepAlive(h)
+}