<commit_before>/*
Package promise provides a complete promise and future implementation.
A quick start sample:


fu := Start(func()(resp interface{}, err error){
    resp, err := http.Get("http://example.com/")
    return
})
//do somthing...
resp, err := fu.Get()
*/
package promise

import (
	"errors"
	"fmt"
	"sync/atomic"
	"time"
	"unsafe"
)

type callbackType int

const (
	CALLBACK_DONE callbackType = iota
	CALLBACK_FAIL
	CALLBACK_ALWAYS
	CALLBACK_CANCEL
)

//pipe presents a promise that will be chain call
type pipe struct {
	pipeDoneTask, pipeFailTask func(v interface{}) *Future
	pipePromise                *Promise
}

//getPipe returns piped Future task function and pipe Promise by the status of current Promise.
func (this *pipe) getPipe(isResolved bool) (func(v interface{}) *Future, *Promise) {
	if isResolved {
		return this.pipeDoneTask, this.pipePromise
	} else {
		return this.pipeFailTask, this.pipePromise
	}
}

//Canceller is used to check if the Promise be requested to cancel and cancel the Promise
//It usually be passed to the real act function for letting act function can cancel the execution.
type Canceller interface {
	IsCancellationRequested() bool
	Cancel()
}

//canceller provides an implement of Canceller interface.
//It will be passed to Future task function as paramter of function
type canceller struct {
	f *Future
}

//RequestCancel sets the status of Promise to CancellationRequested.
//It don't mean the promise be surely cancelled.
//If Future task detects CancellationRequested status, the execution can be stopped.
//Future task must call Cancel() method of Canceller interface to set Future to Cancelled status
func (this *canceller) RequestCancel() {
	//只有当状态==0（表示初始状态）时才可以请求取消任务
	atomic.CompareAndSwapInt32(&this.f.cancelStatus, 0, 1)
}

//IsCancellationRequested returns true if Future task is requested to cancel, otherwise false.
//Future task function can use this method to detect if Future is requested to cancel.
func (this *canceller) IsCancellationRequested() (r bool) {
	return atomic.LoadInt32(&this.f.cancelStatus) == 1
}

//Cancel sets Future task to CANCELLED status
func (this *canceller) Cancel() {
	this.f.Cancel()
}

//IsCancelled returns true if Future task is cancelld, otherwise false.
func (this *canceller) IsCancelled() (r bool) {
	return atomic.LoadInt32(&this.f.cancelStatus) == 2
}

//futureVal stores the internal state of Future.
type futureVal struct {
	dones, fails, always []func(v interface{})
	cancels              []func()
	pipes                []*pipe
	r                    *PromiseResult
}

//Future provides a read-only view of promise,
//the value is set by using Resolve, Reject and Cancel methods of related Promise
type Future struct {
	Id    int //Id can be used as identity of Future
	chOut chan *PromiseResult
	chEnd chan struct{}
	//指向futureVal的指针，程序要保证该指针指向的对象内容不会发送变化，任何变化都必须生成新对象并通过原子操作更新指针，以避免lock
	val          unsafe.Pointer
	cancelStatus int32
}

//Canceller returns a canceller related to future.
//If Canceller return nil, the futrue cannot be cancelled.
func (this *Future) Canceller() Canceller {
	ccstatus := atomic.LoadInt32(&this.cancelStatus)
	if ccstatus >= 0 {
		return &canceller{this}
	} else {
		return nil
	}
}

//RequestCancel request to cancel the promise
//It don't mean the promise be surely cancelled, please refer to canceller.RequestCancel()
func (this *Future) RequestCancel() bool {
	ccstatus := atomic.LoadInt32(&this.cancelStatus)
	if ccstatus == 0 {
		atomic.CompareAndSwapInt32(&this.cancelStatus, 0, 1)
		return true
	} else {
		return false
	}
}

//IsCancelled returns true if the promise is cancelled, otherwise false
func (this *Future) IsCancelled() bool {
	ccstatus := atomic.LoadInt32(&this.cancelStatus)
	return ccstatus == 2
}

//GetChan returns a channel than can be used to receive result of Promise
func (this *Future) GetChan() chan *PromiseResult {
	return this.chOut
}

//Get will block current goroutines until the Future is resolved/rejected/cancelled.
//If Future is resolved, value and nil will be returned
//If Future is rejected, nil and error will be returned.
//If Future is cancelled, nil and CANCELLED error will be returned.
func (this *Future) Get() (val interface{}, err error) {
	<-this.chEnd
	return getFutureReturnVal(this.loadResult())
}

//GetOrTimeout is similar to Get(), but GetOrTimeout will not block after timeout.
//If GetOrTimeout returns with a timeout, timeout value will be true in return values.
//The unit of paramter is millisecond.
func (this *Future) GetOrTimeout(mm int) (val interface{}, err error, timout bool) {
	if mm == 0 {
		mm = 10
	} else {
		mm = mm * 1000 * 1000<commit_msg>Add SetTimeout method for Future<commit_after>/*
Package promise provides a complete promise and future implementation.
A quick start sample:


fu := Start(func()(resp interface{}, err error){
    resp, err := http.Get("http://example.com/")
    return
})
//do somthing...
resp, err := fu.Get()
*/
package promise

import (
	"errors"
	"fmt"
	"sync/atomic"
	"time"
	"unsafe"
)

type callbackType int

const (
	CALLBACK_DONE callbackType = iota
	CALLBACK_FAIL
	CALLBACK_ALWAYS
	CALLBACK_CANCEL
)

//pipe presents a promise that will be chain call
type pipe struct {
	pipeDoneTask, pipeFailTask func(v interface{}) *Future
	pipePromise                *Promise
}

//getPipe returns piped Future task function and pipe Promise by the status of current Promise.
func (this *pipe) getPipe(isResolved bool) (func(v interface{}) *Future, *Promise) {
	if isResolved {
		return this.pipeDoneTask, this.pipePromise
	} else {
		return this.pipeFailTask, this.pipePromise
	}
}

//Canceller is used to check if the Promise be requested to cancel and cancel the Promise
//It usually be passed to the real act function for letting act function can cancel the execution.
type Canceller interface {
	IsCancellationRequested() bool
	Cancel()
}

//canceller provides an implement of Canceller interface.
//It will be passed to Future task function as paramter of function
type canceller struct {
	f *Future
}

//RequestCancel sets the status of Promise to CancellationRequested.
//It don't mean the promise be surely cancelled.
//If Future task detects CancellationRequested status, the execution can be stopped.
//Future task must call Cancel() method of Canceller interface to set Future to Cancelled status
func (this *canceller) RequestCancel() {
	//只有当状态==0（表示初始状态）时才可以请求取消任务
	atomic.CompareAndSwapInt32(&this.f.cancelStatus, 0, 1)
}

//IsCancellationRequested returns true if Future task is requested to cancel, otherwise false.
//Future task function can use this method to detect if Future is requested to cancel.
func (this *canceller) IsCancellationRequested() (r bool) {
	return atomic.LoadInt32(&this.f.cancelStatus) >= 1
}

//Cancel sets Future task to CANCELLED status
func (this *canceller) Cancel() {
	this.f.Cancel()
}

//IsCancelled returns true if Future task is cancelld, otherwise false.
func (this *canceller) IsCancelled() (r bool) {
	return atomic.LoadInt32(&this.f.cancelStatus) == 2
}

//futureVal stores the internal state of Future.
type futureVal struct {
	dones, fails, always []func(v interface{})
	cancels              []func()
	pipes                []*pipe
	r                    *PromiseResult
}

//Future provides a read-only view of promise,
//the value is set by using Resolve, Reject and Cancel methods of related Promise
type Future struct {
	Id    int //Id can be used as identity of Future
	chOut chan *PromiseResult
	chEnd chan struct{}
	//指向futureVal的指针，程序要保证该指针指向的对象内容不会发送变化，任何变化都必须生成新对象并通过原子操作更新指针，以避免lock
	val          unsafe.Pointer
	cancelStatus int32
}

//Canceller returns a canceller related to future.
//If Canceller return nil, the futrue cannot be cancelled.
func (this *Future) Canceller() Canceller {
	ccstatus := atomic.LoadInt32(&this.cancelStatus)
	if ccstatus >= 0 {
		return &canceller{this}
	} else {
		return nil
	}
}

//RequestCancel request to cancel the promise
//It don't mean the promise be surely cancelled, please refer to canceller.RequestCancel()
func (this *Future) RequestCancel() bool {
	ccstatus := atomic.LoadInt32(&this.cancelStatus)
	if ccstatus == 0 {
		atomic.CompareAndSwapInt32(&this.cancelStatus, 0, 1)
		return true
	} else {
		return false
	}
}

//IsCancelled returns true if the promise is cancelled, otherwise false
func (this *Future) IsCancelled() bool {
	ccstatus := atomic.LoadInt32(&this.cancelStatus)
	return ccstatus == 2
}

//Cancel sets the status of promise to RESULT_CANCELLED.
//If promise is cancelled, Get() will return nil and CANCELLED error.
//All callback functions will be not called if Promise is cancalled.
func (this *Future) SetTimeout(mm int) *Future {
	if mm == 0 {
		mm = 10
	} else {
		mm = mm * 1000 * 1000
	}

	go func() {
		<-time.After((time.Duration)(mm) * time.Nanosecond)
		this.Cancel()
	}()
	return this
}

//GetChan returns a channel than can be used to receive result of Promise
func (this *Future) GetChan() chan *PromiseResult {
	return this.chOut
}

//Get will block current goroutines until the Future is resolved/rejected/cancelled.
//If Future is resolved, value and nil will be returned
//If Future is rejected, nil and error will be returned.
//If Future is cancelled, nil and CANCELLED error will be returned.
func (this *Future) Get() (val interface{}, err error) {
	<-this.chEnd
	return getFutureReturnVal(this.loadResult())
}

//GetOrTimeout is similar to Get(), but GetOrTimeout will not block after timeout.
//If GetOrTimeout returns with a timeout, timeout value will be true in return values.
//The unit of paramter is millisecond.
func (this *Future) GetOrTimeout(mm uint) (val interface{}, err error, timout bool) {
	if mm == 0 {
		mm = 10
	} else {
		mm = mm * 1000 * 1000
{'fraction_non_alphanumeric': 0.09171021621067732, 'fraction_numerical': 0.008709908802131365, 'mean_word_length': 4.005128205128205, 'pattern_counts': {'":': 0, '<': 6, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1611513', 'n_tokens_mistral': 3115, 'n_tokens_neox': 3019, 'n_words': 1172}