81 lines
1.9 KiB
Go
81 lines
1.9 KiB
Go
|
package watchdog
|
||
|
|
||
|
import "sync"
|
||
|
|
||
|
var (
|
||
|
gcNotifeeMutex sync.Mutex
|
||
|
gcNotifees []notifeeEntry
|
||
|
|
||
|
forcedGCNotifeeMutex sync.Mutex
|
||
|
forcedGCNotifees []notifeeEntry
|
||
|
)
|
||
|
|
||
|
// RegisterPostGCNotifee registers a function that is called every time a GC has happened,
|
||
|
// both GC runs triggered by the Go runtime and by watchdog.
|
||
|
// The unregister function returned can be used to unregister this notifee.
|
||
|
func RegisterPostGCNotifee(f func()) (unregister func()) {
|
||
|
gcNotifeeMutex.Lock()
|
||
|
defer gcNotifeeMutex.Unlock()
|
||
|
|
||
|
var id int
|
||
|
if len(gcNotifees) > 0 {
|
||
|
id = gcNotifees[len(gcNotifees)-1].id + 1
|
||
|
}
|
||
|
gcNotifees = append(gcNotifees, notifeeEntry{id: id, f: f})
|
||
|
|
||
|
return func() {
|
||
|
gcNotifeeMutex.Lock()
|
||
|
defer gcNotifeeMutex.Unlock()
|
||
|
|
||
|
for i, entry := range gcNotifees {
|
||
|
if entry.id == id {
|
||
|
gcNotifees = append(gcNotifees[:i], gcNotifees[i+1:]...)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func notifyGC() {
|
||
|
if NotifyGC != nil {
|
||
|
NotifyGC()
|
||
|
}
|
||
|
gcNotifeeMutex.Lock()
|
||
|
defer gcNotifeeMutex.Unlock()
|
||
|
for _, entry := range gcNotifees {
|
||
|
entry.f()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// RegisterPreGCNotifee registers a function that is called before watchdog triggers a GC run.
|
||
|
// It is ONLY called when watchdog triggers a GC run, not when the Go runtime triggers it.
|
||
|
// The unregister function returned can be used to unregister this notifee.
|
||
|
func RegisterPreGCNotifee(f func()) (unregister func()) {
|
||
|
forcedGCNotifeeMutex.Lock()
|
||
|
defer forcedGCNotifeeMutex.Unlock()
|
||
|
|
||
|
var id int
|
||
|
if len(forcedGCNotifees) > 0 {
|
||
|
id = forcedGCNotifees[len(forcedGCNotifees)-1].id + 1
|
||
|
}
|
||
|
forcedGCNotifees = append(forcedGCNotifees, notifeeEntry{id: id, f: f})
|
||
|
|
||
|
return func() {
|
||
|
forcedGCNotifeeMutex.Lock()
|
||
|
defer forcedGCNotifeeMutex.Unlock()
|
||
|
|
||
|
for i, entry := range forcedGCNotifees {
|
||
|
if entry.id == id {
|
||
|
forcedGCNotifees = append(forcedGCNotifees[:i], forcedGCNotifees[i+1:]...)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func notifyForcedGC() {
|
||
|
forcedGCNotifeeMutex.Lock()
|
||
|
defer forcedGCNotifeeMutex.Unlock()
|
||
|
for _, entry := range forcedGCNotifees {
|
||
|
entry.f()
|
||
|
}
|
||
|
}
|