mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-11-04 08:32:25 -06:00 
			
		
		
		
	
		
			
	
	
		
			112 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			112 lines
		
	
	
	
		
			2.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package mempool
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"unsafe"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// SimplePool provides a type-safe form
							 | 
						||
| 
								 | 
							
								// of UnsafePool using generics.
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Note it is NOT safe for concurrent
							 | 
						||
| 
								 | 
							
								// use, you must protect it yourself!
							 | 
						||
| 
								 | 
							
								type SimplePool[T any] struct {
							 | 
						||
| 
								 | 
							
									UnsafeSimplePool
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// New is an optionally provided
							 | 
						||
| 
								 | 
							
									// allocator used when no value
							 | 
						||
| 
								 | 
							
									// is available for use in pool.
							 | 
						||
| 
								 | 
							
									New func() T
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Reset is an optionally provided
							 | 
						||
| 
								 | 
							
									// value resetting function called
							 | 
						||
| 
								 | 
							
									// on passed value to Put().
							 | 
						||
| 
								 | 
							
									Reset func(T) bool
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (p *SimplePool[T]) Get() T {
							 | 
						||
| 
								 | 
							
									if ptr := p.UnsafeSimplePool.Get(); ptr != nil {
							 | 
						||
| 
								 | 
							
										return *(*T)(ptr)
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									var t T
							 | 
						||
| 
								 | 
							
									if p.New != nil {
							 | 
						||
| 
								 | 
							
										t = p.New()
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return t
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (p *SimplePool[T]) Put(t T) {
							 | 
						||
| 
								 | 
							
									if p.Reset != nil && !p.Reset(t) {
							 | 
						||
| 
								 | 
							
										return
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									ptr := unsafe.Pointer(&t)
							 | 
						||
| 
								 | 
							
									p.UnsafeSimplePool.Put(ptr)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// UnsafeSimplePool provides an incredibly
							 | 
						||
| 
								 | 
							
								// simple memory pool implementation
							 | 
						||
| 
								 | 
							
								// that stores ptrs to memory values,
							 | 
						||
| 
								 | 
							
								// and regularly flushes internal pool
							 | 
						||
| 
								 | 
							
								// structures according to CheckGC().
							 | 
						||
| 
								 | 
							
								//
							 | 
						||
| 
								 | 
							
								// Note it is NOT safe for concurrent
							 | 
						||
| 
								 | 
							
								// use, you must protect it yourself!
							 | 
						||
| 
								 | 
							
								type UnsafeSimplePool struct {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Check determines how often to flush
							 | 
						||
| 
								 | 
							
									// internal pools based on underlying
							 | 
						||
| 
								 | 
							
									// current and victim pool sizes. It gets
							 | 
						||
| 
								 | 
							
									// called on every pool Put() operation.
							 | 
						||
| 
								 | 
							
									//
							 | 
						||
| 
								 | 
							
									// A flush will start a new current
							 | 
						||
| 
								 | 
							
									// pool, make victim the old current,
							 | 
						||
| 
								 | 
							
									// and drop the existing victim pool.
							 | 
						||
| 
								 | 
							
									Check func(current, victim int) bool
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									current []unsafe.Pointer
							 | 
						||
| 
								 | 
							
									victim  []unsafe.Pointer
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (p *UnsafeSimplePool) Get() unsafe.Pointer {
							 | 
						||
| 
								 | 
							
									// First try current list.
							 | 
						||
| 
								 | 
							
									if len(p.current) > 0 {
							 | 
						||
| 
								 | 
							
										ptr := p.current[len(p.current)-1]
							 | 
						||
| 
								 | 
							
										p.current = p.current[:len(p.current)-1]
							 | 
						||
| 
								 | 
							
										return ptr
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Fallback to victim.
							 | 
						||
| 
								 | 
							
									if len(p.victim) > 0 {
							 | 
						||
| 
								 | 
							
										ptr := p.victim[len(p.victim)-1]
							 | 
						||
| 
								 | 
							
										p.victim = p.victim[:len(p.victim)-1]
							 | 
						||
| 
								 | 
							
										return ptr
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (p *UnsafeSimplePool) Put(ptr unsafe.Pointer) {
							 | 
						||
| 
								 | 
							
									p.current = append(p.current, ptr)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Get GC check func.
							 | 
						||
| 
								 | 
							
									if p.Check == nil {
							 | 
						||
| 
								 | 
							
										p.Check = defaultCheck
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if p.Check(len(p.current), len(p.victim)) {
							 | 
						||
| 
								 | 
							
										p.GC() // garbage collection time!
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (p *UnsafeSimplePool) GC() {
							 | 
						||
| 
								 | 
							
									p.victim = p.current
							 | 
						||
| 
								 | 
							
									p.current = nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func (p *UnsafeSimplePool) Size() int {
							 | 
						||
| 
								 | 
							
									return len(p.current) + len(p.victim)
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func defaultCheck(current, victim int) bool {
							 | 
						||
| 
								 | 
							
									return current-victim > 128 || victim > 256
							 | 
						||
| 
								 | 
							
								}
							 |