// Copyright 2021 PingCAP, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package util import ( "sync" ) // WaitGroupWrapper is a wrapper for sync.WaitGroup type WaitGroupWrapper struct { sync.WaitGroup } // Run runs a function in a goroutine, adds 1 to WaitGroup // and calls done when function returns. Please DO NOT use panic // in the cb function. func (w *WaitGroupWrapper) Run(exec func()) { w.Add(1) go func() { defer w.Done() exec() }() } // RunWithRecover wraps goroutine startup call with force recovery, add 1 to WaitGroup // and call done when function return. it will dump current goroutine stack into log if catch any recover result. // exec is that execute logic function. recoverFn is that handler will be called after recover and before dump stack, // passing `nil` means noop. func (w *WaitGroupWrapper) RunWithRecover(exec func(), recoverFn func(r interface{})) { w.Add(1) go func() { defer func() { r := recover() if r != nil && recoverFn != nil { recoverFn(r) } w.Done() }() exec() }() }