mirror of
https://github.com/gogs/gogs.git
synced 2026-05-05 19:36:27 +02:00
Refactoring: rename modules -> pkg
Reasons to change: 1. Shorter than 'modules' 2. More generally used by other Go projects 3. Corresponds to the naming of '$GOPATH/pkg' directory
This commit is contained in:
70
pkg/sync/exclusive_pool.go
Normal file
70
pkg/sync/exclusive_pool.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// ExclusivePool is a pool of non-identical instances
|
||||
// that only one instance with same identity is in the pool at a time.
|
||||
// In other words, only instances with different identities can be in
|
||||
// the pool the same time. If another instance with same identity tries
|
||||
// to get into the pool, it hangs until previous instance left the pool.
|
||||
//
|
||||
// This pool is particularly useful for performing tasks on same resource
|
||||
// on the file system in different goroutines.
|
||||
type ExclusivePool struct {
|
||||
lock sync.Mutex
|
||||
|
||||
// pool maintains locks for each instance in the pool.
|
||||
pool map[string]*sync.Mutex
|
||||
|
||||
// count maintains the number of times an instance with same identity checks in
|
||||
// to the pool, and should be reduced to 0 (removed from map) by checking out
|
||||
// with same number of times.
|
||||
// The purpose of count is to delete lock when count down to 0 and recycle memory
|
||||
// from map object.
|
||||
count map[string]int
|
||||
}
|
||||
|
||||
// NewExclusivePool initializes and returns a new ExclusivePool object.
|
||||
func NewExclusivePool() *ExclusivePool {
|
||||
return &ExclusivePool{
|
||||
pool: make(map[string]*sync.Mutex),
|
||||
count: make(map[string]int),
|
||||
}
|
||||
}
|
||||
|
||||
// CheckIn checks in an instance to the pool and hangs while instance
|
||||
// with same indentity is using the lock.
|
||||
func (p *ExclusivePool) CheckIn(identity string) {
|
||||
p.lock.Lock()
|
||||
|
||||
lock, has := p.pool[identity]
|
||||
if !has {
|
||||
lock = &sync.Mutex{}
|
||||
p.pool[identity] = lock
|
||||
}
|
||||
p.count[identity]++
|
||||
|
||||
p.lock.Unlock()
|
||||
lock.Lock()
|
||||
}
|
||||
|
||||
// CheckOut checks out an instance from the pool and releases the lock
|
||||
// to let other instances with same identity to grab the lock.
|
||||
func (p *ExclusivePool) CheckOut(identity string) {
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
p.pool[identity].Unlock()
|
||||
if p.count[identity] == 1 {
|
||||
delete(p.pool, identity)
|
||||
delete(p.count, identity)
|
||||
} else {
|
||||
p.count[identity]--
|
||||
}
|
||||
}
|
||||
49
pkg/sync/status_pool.go
Normal file
49
pkg/sync/status_pool.go
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
// StatusTable is a table maintains true/false values.
|
||||
//
|
||||
// This table is particularly useful for un/marking and checking values
|
||||
// in different goroutines.
|
||||
type StatusTable struct {
|
||||
sync.RWMutex
|
||||
pool map[string]bool
|
||||
}
|
||||
|
||||
// NewStatusTable initializes and returns a new StatusTable object.
|
||||
func NewStatusTable() *StatusTable {
|
||||
return &StatusTable{
|
||||
pool: make(map[string]bool),
|
||||
}
|
||||
}
|
||||
|
||||
// Start sets value of given name to true in the pool.
|
||||
func (p *StatusTable) Start(name string) {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
||||
p.pool[name] = true
|
||||
}
|
||||
|
||||
// Stop sets value of given name to false in the pool.
|
||||
func (p *StatusTable) Stop(name string) {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
||||
p.pool[name] = false
|
||||
}
|
||||
|
||||
// IsRunning checks if value of given name is set to true in the pool.
|
||||
func (p *StatusTable) IsRunning(name string) bool {
|
||||
p.RLock()
|
||||
defer p.RUnlock()
|
||||
|
||||
return p.pool[name]
|
||||
}
|
||||
70
pkg/sync/unique_queue.go
Normal file
70
pkg/sync/unique_queue.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2016 The Gogs Authors. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
// UniqueQueue is a queue which guarantees only one instance of same
|
||||
// identity is in the line. Instances with same identity will be
|
||||
// discarded if there is already one in the line.
|
||||
//
|
||||
// This queue is particularly useful for preventing duplicated task
|
||||
// of same purpose.
|
||||
type UniqueQueue struct {
|
||||
table *StatusTable
|
||||
queue chan string
|
||||
}
|
||||
|
||||
// NewUniqueQueue initializes and returns a new UniqueQueue object.
|
||||
func NewUniqueQueue(queueLength int) *UniqueQueue {
|
||||
if queueLength <= 0 {
|
||||
queueLength = 100
|
||||
}
|
||||
|
||||
return &UniqueQueue{
|
||||
table: NewStatusTable(),
|
||||
queue: make(chan string, queueLength),
|
||||
}
|
||||
}
|
||||
|
||||
// Queue returns channel of queue for retrieving instances.
|
||||
func (q *UniqueQueue) Queue() <-chan string {
|
||||
return q.queue
|
||||
}
|
||||
|
||||
// Exist returns true if there is an instance with given indentity
|
||||
// exists in the queue.
|
||||
func (q *UniqueQueue) Exist(id interface{}) bool {
|
||||
return q.table.IsRunning(com.ToStr(id))
|
||||
}
|
||||
|
||||
// AddFunc adds new instance to the queue with a custom runnable function,
|
||||
// the queue is blocked until the function exits.
|
||||
func (q *UniqueQueue) AddFunc(id interface{}, fn func()) {
|
||||
if q.Exist(id) {
|
||||
return
|
||||
}
|
||||
|
||||
idStr := com.ToStr(id)
|
||||
q.table.Lock()
|
||||
q.table.pool[idStr] = true
|
||||
if fn != nil {
|
||||
fn()
|
||||
}
|
||||
q.table.Unlock()
|
||||
q.queue <- idStr
|
||||
}
|
||||
|
||||
// Add adds new instance to the queue.
|
||||
func (q *UniqueQueue) Add(id interface{}) {
|
||||
q.AddFunc(id, nil)
|
||||
}
|
||||
|
||||
// Remove removes instance from the queue.
|
||||
func (q *UniqueQueue) Remove(id interface{}) {
|
||||
q.table.Stop(com.ToStr(id))
|
||||
}
|
||||
Reference in New Issue
Block a user