github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/runtime/internal/luagc/safepool.go (about)

     1  package luagc
     2  
     3  //
     4  // Safe Pool implementation
     5  //
     6  
     7  // SafePool is an implementation of Pool that keeps alive all the values it is
     8  // given.
     9  type SafePool struct {
    10  	markedFinalize []Value
    11  	markedRelease  []Value
    12  }
    13  
    14  func NewSafePool() *SafePool {
    15  	return &SafePool{}
    16  }
    17  
    18  var _ Pool = &SafePool{}
    19  
    20  // Get returns a WeakRef with the given value.  That WeakRef will keep the value
    21  // alive!
    22  func (p *SafePool) Get(v Value) WeakRef {
    23  	return safeWeakRef{v: v}
    24  }
    25  
    26  // Mark adds iface to the list of marked values.
    27  func (p *SafePool) Mark(v Value, flags MarkFlags) {
    28  	if flags&Finalize != 0 {
    29  		p.markedFinalize = appendNoDup(p.markedFinalize, v)
    30  	}
    31  	if flags&Release != 0 {
    32  		p.markedRelease = appendNoDup(p.markedRelease, v)
    33  	}
    34  }
    35  
    36  // append y to the end of xs, removing a previous occurrence of y in xs if
    37  // found.  It is assumed that xs doesn't have any duplicates.
    38  func appendNoDup(xs []Value, y Value) []Value {
    39  	for i, x := range xs {
    40  		if x == y {
    41  			copy(xs[i:], xs[i+1:])
    42  			xs[len(xs)-1] = y
    43  			return xs
    44  		}
    45  	}
    46  	return append(xs, y)
    47  }
    48  
    49  // ExtractPendingFinalize returns nil because all marked values are kept alive by the
    50  // pool.
    51  func (p *SafePool) ExtractPendingFinalize() []Value {
    52  	return nil
    53  }
    54  
    55  // ExtractPendingRelease returns nil because all marked values are kept alive by
    56  // the pool.
    57  func (p *SafePool) ExtractPendingRelease() []Value {
    58  	return nil
    59  }
    60  
    61  // ExtractAllMarkedFinalize returns all values marked for finalizing in reverse
    62  // order, clearing them.
    63  func (p *SafePool) ExtractAllMarkedFinalize() []Value {
    64  	marked := p.markedFinalize
    65  	p.markedFinalize = nil
    66  	reverse(marked)
    67  	return marked
    68  }
    69  
    70  // ExtractAllMarkedRelease returns all values marked for release in reverse
    71  // order, clearing them.
    72  func (p *SafePool) ExtractAllMarkedRelease() []Value {
    73  	marked := p.markedRelease
    74  	p.markedRelease = nil
    75  	reverse(marked)
    76  	return marked
    77  }
    78  
    79  //
    80  // WeakRef implementation for SafePool
    81  //
    82  
    83  // safeWeakRef keeps the value it reference alive.
    84  type safeWeakRef struct {
    85  	v Value
    86  }
    87  
    88  var _ WeakRef = safeWeakRef{}
    89  
    90  // Value returns the value r is referring to.
    91  func (r safeWeakRef) Value() Value {
    92  	return r.v
    93  }
    94  
    95  //
    96  // Helper functions
    97  //
    98  
    99  func reverse(s []Value) {
   100  	for i, j := 0, len(s)-1; i < j; {
   101  		s[i], s[j] = s[j], s[i]
   102  		i++
   103  		j--
   104  	}
   105  }