Skip to content

sync/WaitGroup: new feature WaitWithTimeout #69285

Not planned
@gozoro

Description

@gozoro

Hi!
I would like to have a WaitWithTimeout function in the standard sync/WaitGroup structure.

Example:

package main

import (
	"context"
	"log"
	"os"
	"os/signal"
	"sync"
	"syscall"
	"time"
)

func main() {

	wg := &WaitGroupTimeout{}
	ctx, cancel := context.WithCancel(context.Background())

	var gracefulStopChan = make(chan os.Signal, 1)

	signal.Notify(gracefulStopChan, syscall.SIGTERM, syscall.SIGINT)

	go func() {
		sig := <-gracefulStopChan

		log.Printf("Caught sig: %+v\n", sig)
		log.Println("Application graceful shutdown begin...")

		// Shutdown

		cancel()
		if ok := wg.WaitWithTimeout(10 * time.Second); !ok {
			log.Println("Force shutdown by timeout")
		}
		log.Println("Application graceful shutdown finished")
		os.Exit(1)

	}()

	log.Println("APP start")

	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-ctx.Done():
				//time.Sleep(4 * time.Second)
				for {
					// failed shutdown process or closes something resource
				}
				log.Println("Break the process 1")
				return
			case <-time.After(1 * time.Second):
				log.Println("Process 1")
			}
		}
	}()

	wg.Add(1)
	go func() {
		defer wg.Done()
		for {
			select {
			case <-ctx.Done():
				time.Sleep(5 * time.Second)
				log.Println("Break the process 2")
				return
			case <-time.After(1 * time.Second):
				log.Println("Process 2")
			}
		}
	}()

	wg.Wait()
}

// I would not like to transfer this code from one project to another
type WaitGroupTimeout struct {
	sync.WaitGroup
}

// WaitWithTimeout returns the value "true" when  the [WaitGroup] counter is zero.
// And returns the value "false" when the wait is completed by timeout.
func (wg *WaitGroupTimeout) WaitWithTimeout(timeout time.Duration) bool {

	timeoutChan := time.After(timeout)
	waitChan := make(chan struct{})

	go func() {

		wg.Wait()
		close(waitChan)
	}()

	select {
	case <-timeoutChan:
		return false
	case <-waitChan:
		return true
	}
}

Activity

seankhliao

seankhliao commented on Sep 5, 2024

@seankhliao
Member

Duplicate of #40916

zigo101

zigo101 commented on Sep 5, 2024

@zigo101

It is easy to do this with an additional time.Timer.

gozoro

gozoro commented on Sep 6, 2024

@gozoro
Author

I do this in one line wg.WaitWithTimeout(10 * time.Second). How to put your time.Timer into one function?

zigo101

zigo101 commented on Sep 6, 2024

@zigo101

Certainly, you can't do it in one line.
Programming with channels is fun, why to lose the fun? :D
I mean it is fun to write the code in your first comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @seankhliao@gozoro@zigo101@gabyhelp

      Issue actions

        sync/WaitGroup: new feature WaitWithTimeout · Issue #69285 · golang/go