use container/list to prevent memory leaks
This commit is contained in:
		
							parent
							
								
									5727808a20
								
							
						
					
					
						commit
						92a360708d
					
				
							
								
								
									
										30
									
								
								statement.go
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								statement.go
									
									
									
									
									
								
							@ -1,6 +1,7 @@
 | 
				
			|||||||
package gorm
 | 
					package gorm
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"container/list"
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"database/sql"
 | 
						"database/sql"
 | 
				
			||||||
	"database/sql/driver"
 | 
						"database/sql/driver"
 | 
				
			||||||
@ -60,39 +61,46 @@ type join struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type QueryTypes struct {
 | 
					type QueryTypes struct {
 | 
				
			||||||
	mux  sync.Mutex
 | 
						mux  sync.Mutex
 | 
				
			||||||
	values []bool
 | 
						list *list.List
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (q *QueryTypes) Push(isRows bool) {
 | 
					func (q *QueryTypes) Push(isRows bool) {
 | 
				
			||||||
	q.mux.Lock()
 | 
						q.mux.Lock()
 | 
				
			||||||
	defer q.mux.Unlock()
 | 
						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 {
 | 
					func (q *QueryTypes) Pop() bool {
 | 
				
			||||||
	q.mux.Lock()
 | 
						q.mux.Lock()
 | 
				
			||||||
	defer q.mux.Unlock()
 | 
						defer q.mux.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(q.values) == 0 {
 | 
						if q.list == nil {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						element := q.list.Back()
 | 
				
			||||||
	value := q.values[len(q.values)-1]
 | 
						if element == nil {
 | 
				
			||||||
	q.values = q.values[:len(q.values)-1]
 | 
							return false
 | 
				
			||||||
	return value
 | 
						}
 | 
				
			||||||
 | 
						q.list.Remove(element)
 | 
				
			||||||
 | 
						return element.Value.(bool)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (q *QueryTypes) clone() QueryTypes {
 | 
					func (q *QueryTypes) clone() QueryTypes {
 | 
				
			||||||
	q.mux.Lock()
 | 
						q.mux.Lock()
 | 
				
			||||||
	defer q.mux.Unlock()
 | 
						defer q.mux.Unlock()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(q.values) == 0 {
 | 
						if q.list == nil {
 | 
				
			||||||
		return QueryTypes{}
 | 
							return QueryTypes{}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	values := make([]bool, len(q.values))
 | 
						cloneList := list.New()
 | 
				
			||||||
	copy(values, q.values)
 | 
						for e := q.list.Front(); e != nil; e = e.Next() {
 | 
				
			||||||
	return QueryTypes{values: values}
 | 
							cloneList.PushFront(e.Value)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return QueryTypes{list: cloneList}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// StatementModifier statement modifier interface
 | 
					// StatementModifier statement modifier interface
 | 
				
			||||||
 | 
				
			|||||||
@ -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")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user