use container/list to prevent memory leaks

This commit is contained in:
black 2023-03-13 17:04:55 +08:00
parent 5727808a20
commit 92a360708d
2 changed files with 40 additions and 12 deletions

View File

@ -1,6 +1,7 @@
package gorm
import (
"container/list"
"context"
"database/sql"
"database/sql/driver"
@ -59,40 +60,47 @@ type join struct {
}
type QueryTypes struct {
mux sync.Mutex
values []bool
mux sync.Mutex
list *list.List
}
func (q *QueryTypes) Push(isRows bool) {
q.mux.Lock()
defer q.mux.Unlock()
q.values = append(q.values, isRows)
if q.list == nil {
q.list = list.New()
}
q.list.PushBack(isRows)
}
func (q *QueryTypes) Pop() bool {
q.mux.Lock()
defer q.mux.Unlock()
if len(q.values) == 0 {
if q.list == nil {
return false
}
value := q.values[len(q.values)-1]
q.values = q.values[:len(q.values)-1]
return value
element := q.list.Back()
if element == nil {
return false
}
q.list.Remove(element)
return element.Value.(bool)
}
func (q *QueryTypes) clone() QueryTypes {
q.mux.Lock()
defer q.mux.Unlock()
if len(q.values) == 0 {
if q.list == nil {
return QueryTypes{}
}
values := make([]bool, len(q.values))
copy(values, q.values)
return QueryTypes{values: values}
cloneList := list.New()
for e := q.list.Front(); e != nil; e = e.Next() {
cloneList.PushFront(e.Value)
}
return QueryTypes{list: cloneList}
}
// StatementModifier statement modifier interface

View File

@ -62,3 +62,23 @@ func TestNameMatcher(t *testing.T) {
}
}
}
func TestQueryTypes(t *testing.T) {
types := QueryTypes{}
values := []bool{true, false, false, true}
for _, value := range values {
types.Push(value)
}
clone := types.clone()
for _, value := range values {
actual := clone.Pop()
if actual != value {
t.Errorf("failed to pop, got %v, expect %v", actual, value)
}
}
if clone.list.Len() != 0 || clone.Pop() {
t.Errorf("clone list should be empty")
}
}