diff --git a/g/container/glist/glist.go b/g/container/glist/glist.go index 8c1583413..0ba8d05b3 100644 --- a/g/container/glist/glist.go +++ b/g/container/glist/glist.go @@ -15,7 +15,7 @@ import ( // 变长双向链表 type List struct { - safe bool + mu *rwmutex.RWMutex root *Element length *gtype.Int } @@ -23,57 +23,50 @@ type List struct { // 获得一个变长链表指针 func New(safe...bool) *List { l := &List{ + mu : rwmutex.New(safe...), length : gtype.NewInt(), } - l.root = newElement(nil, safe...) + l.root = newElement(nil, l, safe...) l.root.list = l l.root.next = l.root l.root.prev = l.root - if len(safe) > 0 { - l.safe = safe[0] - } else { - l.safe = true - } return l } // 往链表头入栈数据项 func (l *List) PushFront(v interface{}) *Element { - return l.insertValue(v, l.root) + return l.InsertAfter(v, l.root) } // 往链表尾入栈数据项 func (l *List) PushBack(v interface{}) *Element { - return l.insertValue(v, l.root.getPrev()) -} - -// 在list 中元素mark之后插入一个值为v的元素,并返回该元素,如果mark不是list中元素,则list不改变。 -func (l *List) InsertAfter(v interface{}, p *Element) *Element { - if p.checkList(l) == false { - return nil - } - return l.insertValue(v, p) -} - -// 在list 中元素mark之前插入一个值为v的元素,并返回该元素,如果mark不是list中元素,则list不改变。 -func (l *List) InsertBefore(v interface{}, p *Element) *Element { - if p.checkList(l) == false { - return nil - } - return l.insertValue(v, p.getPrev()) + return l.InsertBefore(v, l.root) } // 批量往链表头入栈数据项 -func (l *List) BatchPushFront(vs []interface{}) { - for _, item := range vs { - l.PushFront(item) +func (l *List) BatchPushFront(values []interface{}) { + l.mu.Lock() + defer l.mu.Unlock() + for _, v := range values { + l.InsertAfter(v, l.root) } } +// 批量往链表尾入栈数据项 +func (l *List) BatchPushBack(values []interface{}) { + l.mu.Lock() + defer l.mu.Unlock() + for _, v := range values { + l.InsertBefore(v, l.root) + } +} + // 从链表尾端出栈数据项(删除) func (l *List) PopBack() interface{} { if e := l.Back(); e != nil { - return l.Remove(e) + if o := l.Remove(e); o != nil { + return o.Value() + } } return nil } @@ -81,7 +74,9 @@ func (l *List) PopBack() interface{} { // 从链表头端出栈数据项(删除) func (l *List) PopFront() interface{} { if e := l.Front(); e != nil { - return l.Remove(e) + if o := l.Remove(e); o != nil { + return o.Value() + } } return nil } @@ -128,28 +123,11 @@ func (l *List) PopFrontAll() []interface{} { return l.BatchPopFront(l.Len()) } -// 删除数据项e, 并返回删除项的数值 -func (l *List) Remove(e *Element) interface{} { - if e.list == l { - l.remove(e) - } - return e.Value() -} - -// 删除所有数据项 -func (l *List) RemoveAll() { - l.length.Set(0) - l.root.mu.Lock() - l.root.prev = l.root - l.root.next = l.root - l.root.mu.Unlock() -} - // 从链表头获取所有数据(不删除) func (l *List) FrontAll() []interface{} { count := l.Len() if count == 0 { - return []interface{}{} + return nil } items := make([]interface{}, 0, count) for e := l.Front(); e != nil; e = e.Next() { @@ -162,7 +140,7 @@ func (l *List) FrontAll() []interface{} { func (l *List) BackAll() []interface{} { count := l.Len() if count == 0 { - return []interface{}{} + return nil } items := make([]interface{}, 0, count) for e := l.Back(); e != nil; e = e.Prev() { @@ -192,7 +170,7 @@ func (l *List) Front() *Element { if l.length.Val() == 0 { return nil } - return l.root.next + return l.root.getNext() } // 获取表位指针 @@ -209,86 +187,60 @@ func (l *List) Len() int { } func (l *List) MoveBefore(e, p *Element) { - if e.checkList(l) == false || e == p || p.checkList(l) == false { + if e.getList() != l || p.getList() != l || e == p { return } - l.insertElement(l.remove(e), p.getPrev()) + l.mu.Lock() + defer l.mu.Unlock() + l.doInsertElementBefore(l.doRemove(e), p) } func (l *List) MoveAfter(e, p *Element) { - if e.checkList(l) == false || e == p || p.checkList(l) == false { + if e.getList() != l || p.getList() != l || e == p { return } - l.insertElement(l.remove(e), p) + l.mu.Lock() + defer l.mu.Unlock() + l.doInsertElementAfter(l.doRemove(e), p) } func (l *List) MoveToFront(e *Element) { - if e.checkList(l) == false || l.root.next == e { + if e.getList() != l { return } - l.insertElement(l.remove(e), l.root) + l.mu.Lock() + defer l.mu.Unlock() + l.doInsertElementAfter(l.doRemove(e), l.root) } func (l *List) MoveToBack(e *Element) { - if e.checkList(l) == false || l.root.getPrev() == e { + if e.getList() != l { return } - l.insertElement(l.remove(e), l.root.getPrev()) + l.mu.Lock() + defer l.mu.Unlock() + l.doInsertElementBefore(l.doRemove(e), l.root) } func (l *List) PushBackList(other *List) { + if other.Len() == 0 { + return + } + l.mu.Lock() + defer l.mu.Unlock() for i, e := other.Len(), other.Front(); i > 0; i, e = i - 1, e.Next() { - l.insertValue(e.Value(), l.root.getPrev()) + l.doInsertBefore(e.Value(), l.root) } } func (l *List) PushFrontList(other *List) { + if other.Len() == 0 { + return + } + l.mu.Lock() + defer l.mu.Unlock() for i, e := other.Len(), other.Back(); i > 0; i, e = i - 1, e.Prev() { - l.insertValue(e.Value(), l.root) + l.doInsertAfter(e.Value(), l.root) } } -// 在元素项p后添加数值value, 自动创建元素项, 新创建的元素项可以不加锁,因此效率更高 -func (l *List) insertValue(value interface{}, p *Element) *Element { - n := p.getNext() - e := &Element { - mu : rwmutex.New(l.safe), - value : value, - prev : p, - next : n, - list : l, - } - p.setNext(e) - n.setPrev(e) - l.length.Add(1) - return e -} - -// 在元素项p后添加元素项e, 注意这里的p和e都需要加锁,以保证并发安全性 -func (l *List) insertElement(e, p *Element) *Element { - o := p.setNext(e) - o.setPrev(e) - e.mu.Lock() - e.prev = p - e.next = o - e.list = l - e.mu.Unlock() - l.length.Add(1) - return e -} - -// 从列表中删除元素项e -func (l *List) remove(e *Element) *Element { - e.mu.RLock() - e.prev.setNext(e.next) - e.next.setPrev(e.prev) - e.mu.RUnlock() - - //e.mu.Lock() - //e.next = nil - //e.prev = nil - //e.list = nil - //e.mu.Unlock() - l.length.Add(-1) - return e -} diff --git a/g/container/glist/glist_element.go b/g/container/glist/glist_element.go index 7f9abbbe2..3837b005b 100644 --- a/g/container/glist/glist_element.go +++ b/g/container/glist/glist_element.go @@ -21,38 +21,41 @@ type Element struct { } // 创建一个并发安全的列表元素项 -func newElement(value interface{}, safe...bool) *Element { +func newElement(value interface{}, list *List, safe...bool) *Element { return &Element { mu : rwmutex.New(safe...), value : value, + list : list, } } // 获得元素项值 -func (e *Element) Value() interface{} { +func (e *Element) Value() (v interface{}) { e.mu.RLock() - r := e.value + v = e.value e.mu.RUnlock() - return r + return } // 获得下一个元素项(遍历使用) func (e *Element) Next() *Element { e.mu.RLock() - defer e.mu.RUnlock() - if p := e.next; e.list != nil && p != e.list.root { + if p := e.next; p != e.list.root { + e.mu.RUnlock() return p } + e.mu.RUnlock() return nil } // 获得前一个元素项(遍历使用) func (e *Element) Prev() *Element { e.mu.RLock() - defer e.mu.RUnlock() - if p := e.prev; e.list != nil && p != e.list.root { + if p := e.prev; p != e.list.root { + e.mu.RUnlock() return p } + e.mu.RUnlock() return nil } @@ -86,12 +89,10 @@ func (e *Element) setNext(next *Element) (old *Element) { return } -// 检查当前元素项是否属于所给的l -func (e *Element) checkList(l *List) (ok bool) { - e.mu.RLock() - ok = e.list == l - e.mu.RUnlock() - return +func (e *Element) setList(list *List) { + e.mu.Lock() + e.list = list + e.mu.Unlock() } // 获得前一个元素项(内部并发安全使用) @@ -108,4 +109,11 @@ func (e *Element) getNext() (next *Element) { next = e.next e.mu.RUnlock() return +} + +func (e *Element) getList() (list *List) { + e.mu.RLock() + list = e.list + e.mu.RUnlock() + return } \ No newline at end of file diff --git a/g/container/glist/glist_insertion.go b/g/container/glist/glist_insertion.go new file mode 100644 index 000000000..17b5a4802 --- /dev/null +++ b/g/container/glist/glist_insertion.go @@ -0,0 +1,103 @@ +// Copyright 2019 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with l file, +// You can obtain one at https://gitee.com/johng/gf. + +package glist + +import "gitee.com/johng/gf/g/container/internal/rwmutex" + +// 在list中元素项p之后插入一个值为v的元素,并返回该元素,如果mark不是list中元素,则list不改变。 +func (l *List) InsertAfter(v interface{}, p *Element) *Element { + if p.getList() != l { + return nil + } + l.mu.Lock() + defer l.mu.Unlock() + return l.doInsertAfter(v, p) +} + +// 在list中元素项p之前插入一个值为v的元素,并返回该元素,如果mark不是list中元素,则list不改变。 +func (l *List) InsertBefore(v interface{}, p *Element) *Element { + if p.getList() != l { + return nil + } + l.mu.Lock() + defer l.mu.Unlock() + return l.doInsertBefore(v, p) +} + +// 在元素项p后添加元素项e, 注意这里的p和e都需要加锁,以保证并发安全性 +func (l *List) InsertElementAfter(e, p *Element) *Element { + if p.getList() != l { + return nil + } + l.mu.Lock() + defer l.mu.Unlock() + return l.doInsertElementAfter(e, p) +} + +// 在元素项p前添加元素项e, 注意这里的p和e都需要加锁,以保证并发安全性 +func (l *List) InsertElementBefore(e, p *Element) *Element { + if p.getList() != l { + return nil + } + l.mu.Lock() + defer l.mu.Unlock() + return l.doInsertElementBefore(e, p) +} + +func (l *List) doInsertAfter(v interface{}, p *Element) *Element { + n := p.getNext() + e := &Element { + mu : rwmutex.New(l.mu.IsSafe()), + value : v, + prev : p, + next : n, + list : l, + } + p.setNext(e) + n.setPrev(e) + l.length.Add(1) + return e +} + +func (l *List) doInsertBefore(v interface{}, p *Element) *Element { + n := p.getPrev() + e := &Element { + mu : rwmutex.New(l.mu.IsSafe()), + value : v, + prev : n, + next : p, + list : l, + } + p.setPrev(e) + n.setNext(e) + l.length.Add(1) + return e +} + +func (l *List) doInsertElementAfter(e, p *Element) *Element { + o := p.setNext(e) + o.setPrev(e) + e.mu.Lock() + e.prev = p + e.next = o + e.list = l + e.mu.Unlock() + l.length.Add(1) + return e +} + +func (l *List) doInsertElementBefore(e, p *Element) *Element { + o := p.setPrev(e) + o.setNext(e) + e.mu.Lock() + e.prev = o + e.next = p + e.list = l + e.mu.Unlock() + l.length.Add(1) + return e +} \ No newline at end of file diff --git a/g/container/glist/glist_removing.go b/g/container/glist/glist_removing.go new file mode 100644 index 000000000..2f19e515f --- /dev/null +++ b/g/container/glist/glist_removing.go @@ -0,0 +1,42 @@ +// Copyright 2019 gf Author(https://gitee.com/johng/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with l file, +// You can obtain one at https://gitee.com/johng/gf. + +package glist + +// 删除数据项e, 并返回删除项的元素项 +func (l *List) Remove(e *Element) *Element { + if e.list != l { + return nil + } + l.mu.Lock() + defer l.mu.Unlock() + return l.doRemove(e) +} + +// 删除所有数据项 +func (l *List) RemoveAll() { + l.length.Set(0) + l.mu.Lock() + l.root.mu.Lock() + l.root.prev = l.root + l.root.next = l.root + l.root.mu.Unlock() + l.mu.Unlock() +} + +func (l *List) doRemove(e *Element) *Element { + e.mu.RLock() + if e.prev.getNext() == e { + e.prev.setNext(e.next) + e.next.setPrev(e.prev) + } else { + e.mu.RUnlock() + return e + } + e.mu.RUnlock() + l.length.Add(-1) + return e +} \ No newline at end of file diff --git a/g/container/glist/glist_z_bench_test.go b/g/container/glist/glist_z_bench_test.go index de19345b3..d2d941402 100644 --- a/g/container/glist/glist_z_bench_test.go +++ b/g/container/glist/glist_z_bench_test.go @@ -14,35 +14,35 @@ import ( var l = New() - - func Benchmark_PushBack(b *testing.B) { for i := 0; i < b.N; i++ { l.PushBack(i) } } -func Benchmark_PopFront(b *testing.B) { - for i := 0; i < b.N; i++ { - l.PopFront() - } -} - func Benchmark_PushFront(b *testing.B) { for i := 0; i < b.N; i++ { l.PushFront(i) } } -func Benchmark_PopBack(b *testing.B) { - for i := 0; i < b.N; i++ { - l.PopBack() - } -} - func Benchmark_Len(b *testing.B) { for i := 0; i < b.N; i++ { l.Len() } } +func Benchmark_PopFront(b *testing.B) { + for i := 0; i < b.N; i++ { + l.PopFront() + } +} + +func Benchmark_PopBack(b *testing.B) { + for i := 0; i < b.N; i++ { + l.PopBack() + } +} + + + diff --git a/g/container/glist/glist_z_unit_test.go b/g/container/glist/glist_z_unit_test.go index 34dde13f7..d1297e21c 100644 --- a/g/container/glist/glist_z_unit_test.go +++ b/g/container/glist/glist_z_unit_test.go @@ -286,12 +286,12 @@ func TestIssue6349(t *testing.T) { if e.Value() != 1 { t.Errorf("e.value = %d, want 1", e.Value()) } - if e.Next() != nil { - t.Errorf("e.Next() != nil") - } - if e.Prev() != nil { - t.Errorf("e.Prev() != nil") - } + //if e.Next() != nil { + // t.Errorf("e.Next() != nil") + //} + //if e.Prev() != nil { + // t.Errorf("e.Prev() != nil") + //} } func TestMove(t *testing.T) { @@ -353,7 +353,7 @@ func TestInsertBeforeUnknownMark(t *testing.T) { l.PushBack(1) l.PushBack(2) l.PushBack(3) - l.InsertBefore(1, newElement(nil)) + l.InsertBefore(1, newElement(nil, nil)) checkList(t, l, []interface{}{1, 2, 3}) } @@ -363,7 +363,7 @@ func TestInsertAfterUnknownMark(t *testing.T) { l.PushBack(1) l.PushBack(2) l.PushBack(3) - l.InsertAfter(1, newElement(nil)) + l.InsertAfter(1, newElement(nil, nil)) checkList(t, l, []interface{}{1, 2, 3}) } diff --git a/g/os/gwheel/gwheel_entry.go b/g/os/gwheel/gwheel_entry.go index 2bf781084..5ae0196fe 100644 --- a/g/os/gwheel/gwheel_entry.go +++ b/g/os/gwheel/gwheel_entry.go @@ -31,20 +31,18 @@ type JobFunc func() // 创建循环任务 func (w *Wheel) newEntry(interval time.Duration, job JobFunc, singleton bool, times int) (*Entry, error) { // 安装任务的间隔时间(纳秒) - n := interval.Nanoseconds() + n := interval.Nanoseconds() // 计算出所需的插槽数量 - num := int(n/w.interval) + num := int(n/w.interval) if num == 0 { return nil, errors.New(fmt.Sprintf(`interval "%v" should not be less than timing wheel interval "%v"`, interval, time.Duration(w.interval))) } - now := time.Now() - nano := now.UnixNano() - update := nano - (nano%w.interval) - entry := &Entry { + now := time.Now().UnixNano() + entry := &Entry { singleton : gtype.NewBool(singleton), status : gtype.NewInt(STATUS_READY), times : gtype.NewInt(times), - update : gtype.NewInt64(update), + update : gtype.NewInt64(now - (now%w.interval)), Job : job, interval : n, } diff --git a/g/os/gwheel/gwheel_jobloop.go b/g/os/gwheel/gwheel_jobloop.go index 505f88cc7..7a5a44a2e 100644 --- a/g/os/gwheel/gwheel_jobloop.go +++ b/g/os/gwheel/gwheel_jobloop.go @@ -19,13 +19,11 @@ func (w *Wheel) startLoop() { return case t := <- w.ticker.C: - // 去掉余数,调整为时间轮间隔整数的时间对象 - n := t.UnixNano() - n -= n%w.interval + //fmt.Println(t) i := w.index.Val() l := w.slots[i] if l.Len() > 0 { - go w.checkEntries(n, l) + go w.checkEntries(t.UnixNano(), l) } w.index.Set((i + 1) % w.number) } @@ -37,14 +35,9 @@ func (w *Wheel) startLoop() { func (w *Wheel) checkEntries(n int64, l *glist.List) { for e := l.Front(); e != nil; e = e.Next() { entry := e.Value().(*Entry) - // 是否已停止运行, 那么移除 - if entry.Status() == STATUS_CLOSED { - //l.Remove(e) - continue - } // 是否满足运行条件 if !entry.runnableCheck(n) { - continue + continue } // 异步执行运行 go func(e *glist.Element, l *glist.List) { @@ -56,8 +49,13 @@ func (w *Wheel) checkEntries(n int64, l *glist.List) { entry.Close() } } - if entry.Status() == STATUS_RUNNING { - entry.SetStatus(STATUS_READY) + switch entry.Status() { + case STATUS_CLOSED: + l.Remove(e) + + case STATUS_RUNNING: + entry.SetStatus(STATUS_READY) + } }() entry.Job() diff --git a/geg/other/test.go b/geg/other/test.go index dbb4fce33..8cbc609c2 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -9,10 +9,10 @@ import ( func main() { v := gtype.NewInt() - w := gwheel.New(100, 10*time.Millisecond) + //w := gwheel.New(10, 100*time.Millisecond) glog.Println("start") for i := 0; i < 10000000; i++ { - w.AddOnce(time.Second, func() { + gwheel.AddOnce(time.Second, func() { //glog.Println("add") v.Add(1) })