github.com/anacrolix/torrent@v1.61.0/internal/indexed/internal-table.go (about)

     1  package indexed
     2  
     3  import (
     4  	"fmt"
     5  	"iter"
     6  
     7  	g "github.com/anacrolix/generics"
     8  	"github.com/anacrolix/missinggo/v2/panicif"
     9  	"github.com/anacrolix/torrent/internal/amortize"
    10  )
    11  
    12  type table[R Record] struct {
    13  	minRecord g.Option[R]
    14  	set       btreeSet[R]
    15  	// Tracks changes to the btree
    16  	version       int
    17  	cmp           CompareFunc[R]
    18  	indexes       []genericRelation
    19  	indexTriggers []triggerFunc[R]
    20  	triggers      []triggerFunc[R]
    21  	inited        bool
    22  }
    23  
    24  func (me *table[R]) GetCmp() CompareFunc[R] {
    25  	return me.cmp
    26  }
    27  
    28  func (me *table[R]) SetMinRecord(min R) {
    29  	panicif.GreaterThan(me.cmp(min, me.minRecord.Value), 0)
    30  	me.minRecord.Set(min)
    31  }
    32  
    33  func (me *table[R]) Init(cmp func(a, b R) int) {
    34  	panicif.True(me.inited)
    35  	me.set = makeAjwernerSet(cmp)
    36  	me.cmp = cmp
    37  	me.inited = true
    38  }
    39  
    40  func (me *table[R]) runTriggers(old, new g.Option[R]) {
    41  	for _, t := range me.triggers {
    42  		t(old, new)
    43  	}
    44  }
    45  
    46  func (me *table[R]) OnChange(t triggerFunc[R]) {
    47  	me.triggers = append(me.triggers, t)
    48  }
    49  
    50  func (me *table[R]) incVersion() {
    51  	me.version++
    52  }
    53  
    54  func (me *table[R]) assertIteratorVersion(it btreeIterator[R]) {
    55  	panicif.NotEq(me.version, it.version)
    56  }
    57  
    58  func (me *table[R]) IterFrom(start R) iter.Seq[R] {
    59  	if me.minRecord.Ok {
    60  		panicif.LessThan(me.cmp(start, me.minRecord.Value), 0)
    61  	}
    62  	return me.set.IterFrom(start)
    63  }
    64  
    65  func (me *table[R]) IterFromWhile(gte R, while func(R) bool) iter.Seq[R] {
    66  	return func(yield func(R) bool) {
    67  		for r := range me.IterFrom(gte) {
    68  			if !while(r) || !yield(r) {
    69  				return
    70  			}
    71  		}
    72  	}
    73  }
    74  
    75  func (me *table[R]) SelectFirstIf(gte R, filter func(r R) bool) (ret g.Option[R]) {
    76  	for r := range me.IterFromWhile(gte, filter) {
    77  		ret.Set(r)
    78  		break
    79  	}
    80  	return
    81  }
    82  
    83  func (me *table[R]) checkWhereGotFirst(first g.Option[R], where func(r R) bool) {
    84  	if !amortize.Try() {
    85  		return
    86  	}
    87  	var slowRet g.Option[R]
    88  	for r := range me.Iter {
    89  		if where(r) {
    90  			slowRet.Set(r)
    91  			break
    92  		}
    93  	}
    94  	if first.Ok != slowRet.Ok || first.Ok && me.cmp(first.Value, slowRet.Value) != 0 {
    95  		fmt.Printf("%#v\n", first.Value)
    96  		fmt.Printf("%#v\n", slowRet.Value)
    97  		panic("herp")
    98  	}
    99  }
   100  
   101  func (me *table[R]) SelectFirstWhere(gte R, where func(r R) bool) (ret g.Option[R]) {
   102  	for r := range me.IterFromWhile(gte, where) {
   103  		ret.Set(r)
   104  		break
   105  	}
   106  	checkWhereGotFirst(me, ret, where)
   107  	return
   108  }
   109  
   110  func (me *table[R]) Delete(r R) (removed bool) {
   111  	remK, removed := me.set.Delete(r)
   112  	me.Changed(g.OptionFromTuple(remK, removed), g.None[R]())
   113  	return
   114  }
   115  
   116  func (me *table[R]) CreateOrReplace(r R) {
   117  	replaced, overwrote := me.set.Upsert(r)
   118  	me.Changed(g.OptionFromTuple(replaced, overwrote), g.Some(r))
   119  }
   120  
   121  func (me *table[R]) Iter(yield func(R) bool) {
   122  	for r := range me.set.Iter {
   123  		if me.minRecord.Ok && amortize.Try() {
   124  			panicif.LessThan(me.cmp(r, me.minRecord.Value), 0)
   125  		}
   126  		if !yield(r) {
   127  			return
   128  		}
   129  	}
   130  }
   131  
   132  func (me *table[R]) Create(r R) (created bool) {
   133  	if me.set.Contains(r) {
   134  		return false
   135  	}
   136  	_, overwrote := me.set.Upsert(r)
   137  	panicif.True(overwrote)
   138  	me.Changed(g.None[R](), g.Some(r))
   139  	return true
   140  }
   141  
   142  func (me *table[R]) Update(r R, updateFunc func(r R) R) (existed bool) {
   143  	existed = me.Contains(r)
   144  	if !existed {
   145  		return false
   146  	}
   147  	newRecord := updateFunc(r)
   148  	if newRecord == r {
   149  		return
   150  	}
   151  	replaced, overwrote := me.set.Upsert(newRecord)
   152  	panicif.False(overwrote)
   153  	panicif.NotZero(me.cmp(r, replaced))
   154  	me.Changed(g.Some(r), g.Some(newRecord))
   155  	return true
   156  }
   157  
   158  // Should this only return a single value ever? Should we check?
   159  func (me *table[R]) Contains(r R) bool {
   160  	return me.set.Contains(r)
   161  }
   162  
   163  func (me *table[R]) Changed(old, new g.Option[R]) {
   164  	// You should not even be trying to change a table underneath iterators. We want to know about
   165  	// this even if nothing happens.
   166  	me.incVersion()
   167  	if !old.Ok && !new.Ok {
   168  		return
   169  	}
   170  	if old.Ok && new.Ok {
   171  		// I believe we have that Records are value-comparable.
   172  		if old.Value == new.Value {
   173  			return
   174  		}
   175  	}
   176  	for _, t := range me.indexTriggers {
   177  		t(old, new)
   178  	}
   179  	me.runTriggers(old, new)
   180  }
   181  
   182  // When you know the existing state and the destination state. Most efficient.
   183  func (me *table[R]) Change(old, new g.Option[R]) {
   184  	if old.Ok {
   185  		if new.Ok {
   186  			// We can't guard deletion in case the compare function is partial, because we may be
   187  			// updating unordered fields.
   188  			_, deleted := me.set.Delete(old.Value)
   189  			panicif.False(deleted)
   190  			_, overwrote := me.set.Upsert(new.Value)
   191  			// What about deleting only if the upsert doesn't clobber here?
   192  			panicif.True(overwrote)
   193  		} else {
   194  			_, deleted := me.set.Delete(old.Value)
   195  			panicif.False(deleted)
   196  		}
   197  	} else {
   198  		if new.Ok {
   199  			_, overwrote := me.set.Upsert(new.Value)
   200  			panicif.True(overwrote)
   201  		} else {
   202  			return
   203  		}
   204  	}
   205  	me.Changed(old, new)
   206  }
   207  
   208  func (me *table[R]) GetFirst() (r R, ok bool) {
   209  	for r = range me.Iter {
   210  		ok = true
   211  		break
   212  	}
   213  	if amortize.Try() {
   214  		panicif.NotEq(g.OptionFromTuple(r, ok), me.GetGte(me.MinRecord()))
   215  	}
   216  	return
   217  }
   218  
   219  // Gets the first record greater than or equal. Hope to avoid allocation for iterator.
   220  func (me *table[R]) GetGte(r R) (ret g.Option[R]) {
   221  	// Don't need version checking since we don't iterate.
   222  	for ret.Value = range me.IterFrom(r) {
   223  		ret.Ok = true
   224  		break
   225  	}
   226  	return
   227  }
   228  
   229  // Not count because that could imply more than O(1) work.
   230  func (me *table[R]) Len() int {
   231  	return me.set.Len()
   232  }
   233  
   234  // Returns the minimal record of type R, which may not be the same as the zero value for the record.
   235  // Convenient to avoid having to look up complex types for small expressions. Could be a global
   236  // function. Should definitely be if this is invoked through an interface. Panics if the min record
   237  // wasn't set. The concept of MinRecord might be flawed if there are conditions in the ordering of
   238  // values in a record. In that case the user may have to modify "intermediate" fields in order to
   239  // set a GTE record that's appropriate midway in the table.
   240  func (me *table[R]) MinRecord() (_ R) {
   241  	return me.minRecord.Unwrap()
   242  }