add sync.Cond
Этот коммит содержится в:
		
							родитель
							
								
									171d0fe123
								
							
						
					
					
						коммит
						ccd79ee289
					
				
					 2 изменённых файлов: 85 добавлений и 0 удалений
				
			
		
							
								
								
									
										80
									
								
								src/sync/cond.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										80
									
								
								src/sync/cond.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
					@ -0,0 +1,80 @@
 | 
				
			||||||
 | 
					package sync
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "internal/task"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Cond struct {
 | 
				
			||||||
 | 
						L Locker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						unlocking *earlySignal
 | 
				
			||||||
 | 
						blocked   task.Stack
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// earlySignal is a type used to implement a stack for signalling waiters while they are unlocking.
 | 
				
			||||||
 | 
					type earlySignal struct {
 | 
				
			||||||
 | 
						next *earlySignal
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						signaled bool
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cond) trySignal() bool {
 | 
				
			||||||
 | 
						// Pop a blocked task off of the stack, and schedule it if applicable.
 | 
				
			||||||
 | 
						t := c.blocked.Pop()
 | 
				
			||||||
 | 
						if t != nil {
 | 
				
			||||||
 | 
							scheduleTask(t)
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If there any tasks which are currently unlocking, signal one.
 | 
				
			||||||
 | 
						if c.unlocking != nil {
 | 
				
			||||||
 | 
							c.unlocking.signaled = true
 | 
				
			||||||
 | 
							c.unlocking = c.unlocking.next
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// There was nothing to signal.
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cond) Signal() {
 | 
				
			||||||
 | 
						c.trySignal()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cond) Broadcast() {
 | 
				
			||||||
 | 
						// Signal everything.
 | 
				
			||||||
 | 
						for c.trySignal() {
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Cond) Wait() {
 | 
				
			||||||
 | 
						// Add an earlySignal frame to the stack so we can be signalled while unlocking.
 | 
				
			||||||
 | 
						early := earlySignal{
 | 
				
			||||||
 | 
							next: c.unlocking,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						c.unlocking = &early
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Temporarily unlock L.
 | 
				
			||||||
 | 
						c.L.Unlock()
 | 
				
			||||||
 | 
						defer c.L.Lock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If we were signaled while unlocking, immediately complete.
 | 
				
			||||||
 | 
						if early.signaled {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Remove the earlySignal frame.
 | 
				
			||||||
 | 
						if c.unlocking == &early {
 | 
				
			||||||
 | 
							c.unlocking = early.next
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// Something else happened after the unlock - the earlySignal is somewhere in the middle.
 | 
				
			||||||
 | 
							// This would be faster but less space-efficient if it were a doubly linked list.
 | 
				
			||||||
 | 
							prev := c.unlocking
 | 
				
			||||||
 | 
							for prev.next != &early {
 | 
				
			||||||
 | 
								prev = prev.next
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							prev.next = early.next
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Wait for a signal.
 | 
				
			||||||
 | 
						c.blocked.Push(task.Current())
 | 
				
			||||||
 | 
						task.Pause()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -69,3 +69,8 @@ func (rw *RWMutex) RUnlock() {
 | 
				
			||||||
		rw.m.Unlock()
 | 
							rw.m.Unlock()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Locker interface {
 | 
				
			||||||
 | 
						Lock()
 | 
				
			||||||
 | 
						Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче