Skip to content

Commit

Permalink
Imlemented ResetStepsAndCancelReason() (google#433)
Browse files Browse the repository at this point in the history
* Imlemented ResetStepsAndCancelReason()

* Imlemented Uncancel() and make steps public

* fix comments
  • Loading branch information
vanishs authored Oct 19, 2022
1 parent 6bf6f09 commit 6ce4ce3
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 12 deletions.
28 changes: 18 additions & 10 deletions starlark/eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,13 @@ type Thread struct {
// The default behavior is to call thread.Cancel("too many steps").
OnMaxSteps func(thread *Thread)

// steps counts abstract computation steps executed by this thread.
steps, maxSteps uint64
// Steps a count of abstract computation steps executed
// by this thread. It is incremented by the interpreter. It may be used
// as a measure of the approximate cost of Starlark execution, by
// computing the difference in its value before and after a computation.
//
// The precise meaning of "step" is not specified and may change.
Steps, maxSteps uint64

// cancelReason records the reason from the first call to Cancel.
cancelReason *string
Expand All @@ -65,14 +70,9 @@ type Thread struct {
proftime time.Duration
}

// ExecutionSteps returns a count of abstract computation steps executed
// by this thread. It is incremented by the interpreter. It may be used
// as a measure of the approximate cost of Starlark execution, by
// computing the difference in its value before and after a computation.
//
// The precise meaning of "step" is not specified and may change.
// ExecutionSteps returns the current value of Steps.
func (thread *Thread) ExecutionSteps() uint64 {
return thread.steps
return thread.Steps
}

// SetMaxExecutionSteps sets a limit on the number of Starlark
Expand All @@ -84,12 +84,20 @@ func (thread *Thread) SetMaxExecutionSteps(max uint64) {
thread.maxSteps = max
}

// Uncancel resets the cancellation state.
//
// Unlike most methods of Thread, it is safe to call Uncancel from any
// goroutine, even if the thread is actively executing.
func (thread *Thread) Uncancel() {
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&thread.cancelReason)), nil)
}

// Cancel causes execution of Starlark code in the specified thread to
// promptly fail with an EvalError that includes the specified reason.
// There may be a delay before the interpreter observes the cancellation
// if the thread is currently in a call to a built-in function.
//
// Cancellation cannot be undone.
// Call [Uncancel] to reset the cancellation state.
//
// Unlike most methods of Thread, it is safe to call Cancel from any
// goroutine, even if the thread is actively executing.
Expand Down
7 changes: 7 additions & 0 deletions starlark/eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -972,6 +972,13 @@ func TestExecutionSteps(t *testing.T) {
if fmt.Sprint(err) != "Starlark computation cancelled: too many steps" {
t.Errorf("execution returned error %q, want cancellation", err)
}

thread.Steps = 0
thread.Uncancel()
_, err = countSteps(1)
if err != nil {
t.Errorf("execution returned error %q, want nil", err)
}
}

// TestDeps fails if the interpreter proper (not the REPL, etc) sprouts new external dependencies.
Expand Down
4 changes: 2 additions & 2 deletions starlark/interp.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ func (fn *Function) CallInternal(thread *Thread, args Tuple, kwargs []Tuple) (Va
code := f.Code
loop:
for {
thread.steps++
if thread.steps >= thread.maxSteps {
thread.Steps++
if thread.Steps >= thread.maxSteps {
if thread.OnMaxSteps != nil {
thread.OnMaxSteps(thread)
} else {
Expand Down

0 comments on commit 6ce4ce3

Please sign in to comment.