Skip to content

Commit

Permalink
feat(logic): add limit context
Browse files Browse the repository at this point in the history
  • Loading branch information
ccamel committed Jan 6, 2023
1 parent 4b91db4 commit 3569103
Show file tree
Hide file tree
Showing 2 changed files with 133 additions and 0 deletions.
34 changes: 34 additions & 0 deletions x/logic/context/limit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package context

import (
"context"
"sync/atomic"
)

// IncrementCountByFunc is a function that increments the count value by the provided delta.
type IncrementCountByFunc func(delta uint64) uint64

func (f IncrementCountByFunc) By(delta uint64) func() uint64 {
return func() uint64 {
return f(delta)
}
}

// WithLimit returns a copy of the parent context with a limit adjusted to the provided value, and a function that
// increments the count value. When the count value exceeds the limit, the returned context's Done channel is closed.
// The returned context's Done channel is also closed when the returned cancel function is called, or when the parent
// context's Done channel is closed, whichever happens first.
// Canceling this context releases resources associated with it, so code should call cancel as soon as the operations
// running in this Context complete.
func WithLimit(parent context.Context, limit uint64) (context.Context, IncrementCountByFunc) {
var counter uint64
ctx, cancel := context.WithCancel(parent)

return ctx, func(delta uint64) uint64 {
new := atomic.AddUint64(&counter, delta)
if new > limit {
cancel()
}
return new
}
}
99 changes: 99 additions & 0 deletions x/logic/interpreter/instrument.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package interpreter

import (
"github.com/ichiban/prolog/engine"
)

type Callback[T any] func() T

// Instrument1 is a higher order function that given a 1arg-predicate and a callback returns a new predicate that calls the
// callback before calling the predicate.
func Instrument1[T any](callback Callback[T], p engine.Predicate1) engine.Predicate1 {
return func(vm *engine.VM, t1 engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
callback()

return p(vm, t1, cont, env)
}
}

// Instrument2 is a higher order function that given a 2args-predicate and a callback returns a new predicate that calls the
// callback before calling the predicate.
func Instrument2[T any](callback Callback[T], p engine.Predicate2) engine.Predicate2 {
return func(vm *engine.VM, t1 engine.Term, t2 engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
callback()

return p(vm, t1, t2, cont, env)
}
}

// Instrument3 is a higher order function that given a 3args-predicate and a callback returns a new predicate that calls the
// callback before calling the predicate.
func Instrument3[T any](callback Callback[T], p engine.Predicate3) engine.Predicate3 {
return func(vm *engine.VM, t1 engine.Term, t2 engine.Term, t3 engine.Term, cont engine.Cont,
env *engine.Env,
) *engine.Promise {
callback()

return p(vm, t1, t2, t3, cont, env)
}
}

// Instrument4 is a higher order function that given a 4args-predicate and a callback returns a new predicate that calls the
// callback before calling the predicate.
//
//nolint:lll
func Instrument4[T any](callback Callback[T], p engine.Predicate4) engine.Predicate4 {
return func(vm *engine.VM, t1 engine.Term, t2 engine.Term, t3 engine.Term, t4 engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
callback()

return p(vm, t1, t2, t3, t4, cont, env)
}
}

// Instrument5 is a higher order function that given a 5args-predicate and a callback returns a new predicate that calls the
// callback before calling the predicate.
//
//nolint:lll
func Instrument5[T any](callback Callback[T], p engine.Predicate5) engine.Predicate5 {
return func(vm *engine.VM, t1 engine.Term, t2 engine.Term, t3 engine.Term, t4 engine.Term, t5 engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
callback()

return p(vm, t1, t2, t3, t4, t5, cont, env)
}
}

// Instrument6 is a higher order function that given a 6args-predicate and a callback returns a new predicate that calls the
// callback before calling the predicate.
//
//nolint:lll
func Instrument6[T any](callback Callback[T], p engine.Predicate6) engine.Predicate6 {
return func(vm *engine.VM, t1 engine.Term, t2 engine.Term, t3 engine.Term, t4 engine.Term, t5 engine.Term, t6 engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
callback()

return p(vm, t1, t2, t3, t4, t5, t6, cont, env)
}
}

// Instrument7 is a higher order function that given a 7args-predicate and a callback returns a new predicate that calls the
// callback before calling the predicate.
//
//nolint:lll
func Instrument7[T any](callback Callback[T], p engine.Predicate7) engine.Predicate7 {
return func(vm *engine.VM, t1 engine.Term, t2 engine.Term, t3 engine.Term, t4 engine.Term, t5 engine.Term, t6 engine.Term, t7 engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
callback()

return p(vm, t1, t2, t3, t4, t5, t6, t7, cont, env)
}
}

// Instrument8 is a higher order function that given a 8args-predicate and a callback returns a new predicate that calls the
// callback before calling the predicate.
//
//nolint:lll
func Instrument8[T any](callback Callback[T], p engine.Predicate8) engine.Predicate8 {
return func(vm *engine.VM, t1 engine.Term, t2 engine.Term, t3 engine.Term, t4 engine.Term, t5 engine.Term, t6 engine.Term, t7 engine.Term, t8 engine.Term, cont engine.Cont, env *engine.Env) *engine.Promise {
callback()

return p(vm, t1, t2, t3, t4, t5, t6, t7, t8, cont, env)
}
}

0 comments on commit 3569103

Please sign in to comment.