func TestNoRaceCond(t *testing.T) { // tsan's test02 ch := make(chan bool, 1) var x int = 0 var mu sync.Mutex var cond *sync.Cond = sync.NewCond(&mu) var condition int = 0 var waker func() waker = func() { x = 1 mu.Lock() condition = 1 cond.Signal() mu.Unlock() } var waiter func() waiter = func() { go waker() cond.L.Lock() for condition != 1 { cond.Wait() } cond.L.Unlock() x = 2 ch <- true } go waiter() <-ch }
func main() { var mtx sync.Mutex var cnd *sync.Cond var cnds [N]*sync.Cond var mtxs [N]sync.Mutex cnd = sync.NewCond(&mtx) for i := 0; i < N; i++ { cnds[i] = sync.NewCond(&mtxs[i]) } for i := 0; i < N; i++ { go func(me int, m *sync.Mutex, c1 *sync.Cond, c2 *sync.Cond) { fmt.Printf("Hello, world. %d\n", me) if me == 0 { cnd.Signal() } for j := 0; j < 10000000; j++ { m.Lock() c1.Wait() m.Unlock() c2.Signal() } if me == N-1 { cnd.Signal() } }(i, &mtxs[i], cnds[i], cnds[(i+1)%N]) } mtx.Lock() cnd.Wait() mtx.Unlock() cnds[0].Signal() mtx.Lock() cnd.Wait() mtx.Unlock() }
func (tasks Tasks) RunTasksWithTimeout(stopTime time.Time) { finishedTasks := 0 waitCond := new(sync.Cond) waitCond.L = new(sync.Mutex) done := make(chan bool, 1) current_running := 0 for _, task := range tasks { waitCond.L.Lock() for current_running >= numWorkers { waitCond.Wait() } current_running++ waitCond.L.Unlock() go func(task *Task) { todo := len(tasks) - finishedTasks - (numWorkers - 1) if todo < 1 { todo = 1 } duration := stopTime.Sub(time.Now()) / time.Duration(todo) dprint(duration) task.stopTime = time.Now().Add(duration) go task.Run() <-task.ch if task.timed_out { dprint("Timeout occured.") } else { dprint("Finished normally.") } waitCond.L.Lock() current_running-- finishedTasks++ if finishedTasks == len(tasks) { done <- true } waitCond.Signal() waitCond.L.Unlock() }(task) } <-done }
//TODO return after sending request immediately func post(url string, payload io.Reader, cond *sync.Cond, ratio int, ready chan bool) { cond.L.Lock() ready <- true cond.Wait() cond.L.Unlock() log.Printf("++post: %s", url) u := url if !strings.HasPrefix(u, "http://") { u = "http://" + u } if !strings.HasSuffix(u, "/") { u = u + "/" } u = u + "download" resp, err := http.Post(u, "application/json", payload) if err != nil { log.Printf("post to %s error: %s", url, err.Error()) return } if resp.StatusCode != 200 { log.Printf("post to %s error, status code %d", url, resp.StatusCode) return } log.Printf("--post: %s", url) for i := 0; i < ratio; i++ { cond.L.Lock() cond.Signal() cond.L.Unlock() } }
func TestRaceCond(t *testing.T) { // tsan's test50 ch := make(chan bool, 2) var x int = 0 var mu sync.Mutex var condition int = 0 var cond *sync.Cond = sync.NewCond(&mu) var waker func() = func() { <-time.After(1e5) x = 1 mu.Lock() condition = 1 cond.Signal() mu.Unlock() <-time.After(1e5) mu.Lock() x = 3 mu.Unlock() ch <- true } var waiter func() = func() { mu.Lock() for condition != 1 { cond.Wait() } mu.Unlock() x = 2 ch <- true } x = 0 go waker() go waiter() <-ch <-ch }
func cleanHistory(channelID string, api *slack.Client, msgQueue *utility.Queue, histSize int, histCond *sync.Cond, threadWait *sync.WaitGroup) { defer threadWait.Done() defer histCond.Signal() histCond.L.Lock() defer histCond.L.Unlock() logging.Log.Infof("(%s) Starting cleanHistory", channelID) histParams := slack.NewHistoryParameters() histParams.Inclusive = true histCountMax := 1000 // build history with histSize messages logging.Log.Infof("(%s) Building history with %v messages", channelID, histSize) var history *slack.History var histErr error nRemaining := histSize for nRemaining > 0 { if nRemaining > histCountMax { histParams.Count = histCountMax } else { histParams.Count = nRemaining } history, histErr = api.GetChannelHistory(channelID, histParams) if histErr != nil { logging.Log.Errorf("(%s) Unable to get the channel history: %v", channelID, histErr) return } iLastMsg := len(history.Messages) - 1 //logging.Log.Debug("0: %v, %v: %v", history.Messages[0].Timestamp, iLastMsg, history.Messages[iLastMsg].Timestamp) logging.Log.Debugf("(%s) In skip loop; obtained history with %v messages", channelID, len(history.Messages)) for iMsg := iLastMsg; iMsg >= 0; iMsg-- { msgQueue.Push(history.Messages[iMsg].Timestamp) //logging.Log.Debugf("(%s) Pushing to queue: %s", channelID, history.Messages[iMsg].Timestamp) } if !history.HasMore { return } histParams.Latest = history.Messages[iLastMsg].Timestamp histParams.Inclusive = false nRemaining -= histCountMax } histParams.Count = histCountMax nDeleted := 0 for history.HasMore == true { history, histErr = api.GetChannelHistory(channelID, histParams) if histErr != nil { logging.Log.Errorf("(%s) Unable to get the channel history: %v", channelID, histErr) return } logging.Log.Debugf("(%s) Deleting %v items (latest: %v)", channelID, len(history.Messages), history.Latest) for _ /*iMsg*/, message := range history.Messages { //logging.Log.Debugf("(%s) Deleting: %s", channelID, message.Timestamp) _, _ /*respChan, respTS,*/, respErr := api.DeleteMessage(channelID, message.Timestamp) if respErr != nil { logging.Log.Warningf("(%s) Unable to delete message: %v", channelID, respErr) } //logging.Log.Debugf("(%s) Deletion response: %s, %s, %v", channelID, respChan, respTS, respErr) nDeleted++ } histParams.Latest = history.Messages[len(history.Messages)-1].Timestamp } logging.Log.Noticef("(%s) Deleted %v messages", channelID, nDeleted) return }