github.com/tursom/GoCollections@v0.3.10/concurrent/future/Future.go (about)

     1  package future
     2  
     3  import (
     4  	"github.com/tursom/GoCollections/exceptions"
     5  	"github.com/tursom/GoCollections/lang"
     6  	"github.com/tursom/GoCollections/util/time"
     7  )
     8  
     9  type (
    10  	Future[T any] interface {
    11  		Get() (T, exceptions.Exception)
    12  		GetT(timeout time.Duration) (T, exceptions.Exception)
    13  		IsDone() bool
    14  		IsCancelled() bool
    15  		Cancel() bool
    16  	}
    17  
    18  	Task[T any] interface {
    19  		Future[T]
    20  		Done(value T)
    21  		Fail(e exceptions.Exception)
    22  	}
    23  
    24  	futureState uint8
    25  
    26  	impl[T any] struct {
    27  		state     futureState
    28  		value     T
    29  		e         exceptions.Exception
    30  		done      chan futureState
    31  		canceller func() bool
    32  	}
    33  )
    34  
    35  //goland:noinspection GoSnakeCaseUsage
    36  const (
    37  	futureState_start    futureState = iota
    38  	futureState_done     futureState = iota
    39  	futureState_canceled futureState = iota
    40  )
    41  
    42  func Get[T any](future Future[T]) T {
    43  	get, e := future.Get()
    44  	if e != nil {
    45  		panic(e)
    46  	}
    47  
    48  	return get
    49  }
    50  
    51  func GetT[T any](future Future[T], timeout time.Duration) T {
    52  	get, e := future.GetT(timeout)
    53  	if e != nil {
    54  		panic(e)
    55  	}
    56  
    57  	return get
    58  }
    59  
    60  func New[T any](canceller func() bool) Task[T] {
    61  	return &impl[T]{
    62  		done:      make(chan futureState, 1),
    63  		canceller: canceller,
    64  	}
    65  }
    66  
    67  func (i *impl[T]) Done(value T) {
    68  	if i.IsDone() {
    69  		return
    70  	}
    71  
    72  	i.value = value
    73  	i.state = futureState_done
    74  	i.done <- futureState_done
    75  }
    76  
    77  func (i *impl[T]) Fail(e exceptions.Exception) {
    78  	if i.IsDone() {
    79  		return
    80  	}
    81  
    82  	i.e = e
    83  	i.state = futureState_done
    84  	i.done <- futureState_done
    85  }
    86  
    87  func (i *impl[T]) Get() (T, exceptions.Exception) {
    88  	if i.IsDone() {
    89  		return i.value, i.e
    90  	}
    91  
    92  	<-i.done
    93  
    94  	return i.value, i.e
    95  }
    96  
    97  func (i *impl[T]) GetT(timeout time.Duration) (T, exceptions.Exception) {
    98  	if i.IsDone() {
    99  		return i.value, i.e
   100  	}
   101  
   102  	select {
   103  	case i.state = <-i.done:
   104  	case <-time.After(timeout):
   105  		return lang.Nil[T](), exceptions.NewTimeoutException(
   106  			"Future.GetT timeout", nil)
   107  	}
   108  
   109  	return i.value, i.e
   110  }
   111  
   112  func (i *impl[T]) IsDone() bool {
   113  	return i.state != futureState_start
   114  }
   115  
   116  func (i *impl[T]) IsCancelled() bool {
   117  	return i.state == futureState_canceled
   118  }
   119  
   120  func (i *impl[T]) Cancel() bool {
   121  	if i.IsDone() {
   122  		return false
   123  	}
   124  
   125  	if !i.canceller() {
   126  		return false
   127  	}
   128  
   129  	i.state = futureState_canceled
   130  	i.done <- futureState_canceled
   131  	return true
   132  }