You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							66 lines
						
					
					
						
							1.4 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							66 lines
						
					
					
						
							1.4 KiB
						
					
					
				| package util | |
| 
 | |
| // initial version comes from https://hackernoon.com/asyncawait-in-golang-an-introductory-guide-ol1e34sg | |
|  | |
| import ( | |
| 	"container/list" | |
| 	"context" | |
| 	"sync" | |
| ) | |
| 
 | |
| type Future interface { | |
| 	Await() interface{} | |
| } | |
| 
 | |
| type future struct { | |
| 	await func(ctx context.Context) interface{} | |
| } | |
| 
 | |
| func (f future) Await() interface{} { | |
| 	return f.await(context.Background()) | |
| } | |
| 
 | |
| type LimitedAsyncExecutor struct { | |
| 	executor       *LimitedConcurrentExecutor | |
| 	futureList     *list.List | |
| 	futureListCond *sync.Cond | |
| } | |
| 
 | |
| func NewLimitedAsyncExecutor(limit int) *LimitedAsyncExecutor { | |
| 	return &LimitedAsyncExecutor{ | |
| 		executor:       NewLimitedConcurrentExecutor(limit), | |
| 		futureList:     list.New(), | |
| 		futureListCond: sync.NewCond(&sync.Mutex{}), | |
| 	} | |
| } | |
| 
 | |
| func (ae *LimitedAsyncExecutor) Execute(job func() interface{}) { | |
| 	var result interface{} | |
| 	c := make(chan struct{}) | |
| 	ae.executor.Execute(func() { | |
| 		defer close(c) | |
| 		result = job() | |
| 	}) | |
| 	f := future{await: func(ctx context.Context) interface{} { | |
| 		select { | |
| 		case <-ctx.Done(): | |
| 			return ctx.Err() | |
| 		case <-c: | |
| 			return result | |
| 		} | |
| 	}} | |
| 	ae.futureListCond.L.Lock() | |
| 	ae.futureList.PushBack(f) | |
| 	ae.futureListCond.Signal() | |
| 	ae.futureListCond.L.Unlock() | |
| } | |
| 
 | |
| func (ae *LimitedAsyncExecutor) NextFuture() Future { | |
| 	ae.futureListCond.L.Lock() | |
| 	for ae.futureList.Len() == 0 { | |
| 		ae.futureListCond.Wait() | |
| 	} | |
| 	f := ae.futureList.Remove(ae.futureList.Front()) | |
| 	ae.futureListCond.L.Unlock() | |
| 	return f.(Future) | |
| }
 |