Error processing request
Parameters
CONTENT_LENGTH | 0 |
REQUEST_METHOD | GET |
REQUEST_URI | /revision/After+Task+Scheduler?V=2 |
QUERY_STRING | V=2 |
CONTENT_TYPE | |
DOCUMENT_URI | /revision/After+Task+Scheduler |
DOCUMENT_ROOT | /var/www/nikit/nikit/nginx/../docroot |
SCGI | 1 |
SERVER_PROTOCOL | HTTP/1.1 |
REMOTE_ADDR | 172.69.6.22 |
REMOTE_PORT | 45110 |
SERVER_PORT | 8888 |
SERVER_NAME | wiki.tcl-lang.org |
HTTP_HOST | wiki.tcl-lang.org |
HTTP_CONNECTION | Keep-Alive |
HTTP_ACCEPT_ENCODING | gzip |
HTTP_X_FORWARDED_FOR | 3.143.205.169 |
HTTP_CF_RAY | 886260f4d9856157-ORD |
HTTP_X_FORWARDED_PROTO | http |
HTTP_CF_VISITOR | {"scheme":"http"} |
HTTP_ACCEPT | */* |
HTTP_USER_AGENT | Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; [email protected]) |
HTTP_CF_CONNECTING_IP | 3.143.205.169 |
HTTP_CDN_LOOP | cloudflare |
HTTP_CF_IPCOUNTRY | US |
Body
Error
Unknow state transition: LINE -> END
-code
1
-level
0
-errorstack
INNER {returnImm {Unknow state transition: LINE -> END} {}} CALL {my render_wikit {After Task Scheduler} {[George Peter Staplin]: As a fun experiment with cooperative task scheduling I implemented this prototype.
----
# By George Peter Staplin -- Dec 19, 2005 - Jan 5, 2006
# This implements a task scheduler using [after].
# It supports (so far) 2 scheduling algorithms -- alternating and sequential.
# This is version 4 of a prototype.
array set ::tasks {}
set ::task_counter 0
set ::run_queue [list]
proc assert body {
if {![uplevel 1 $body]} {
return -code error "assertion failed: $body"
}
}
proc task {start iterator end data} {
global tasks task_counter
incr task_counter
while {[info exists tasks($task_counter)]} {
incr task_counter
}
lappend tasks(list) $task_counter
set tasks($task_counter) $task_counter
#
# The valid states are NOT_RUNNING, RUNNING, DONE.
#
set tasks($task_counter,state) NOT_RUNNING
set tasks($task_counter,start) $start
set tasks($task_counter,iterator) $iterator
set tasks($task_counter,end) $end
set tasks($task_counter,data) $data
return $task_counter
}
proc reset.tasks {} {
global tasks
foreach t $tasks(list) {
set tasks($t,state) NOT_RUNNING
}
}
proc run.tasks algorithm {
global tasks
global run_queue
lappend run_queue $algorithm
if {[llength $run_queue] > 1} {
#
# We will handle this after the current task queue finishes.
#
return
}
switch -- $algorithm {
sequential - alternating {}
default {
return -code error "invalid scheduler algorithm"
}
}
after 1 start.task $tasks([lindex $tasks(list) 0]) $algorithm
}
proc possibly.start.task task {
global tasks
#
# This is used to prevent starting a task multiple times.
#
if {"RUNNING" ne $tasks($task,state)} {
set tasks($task,state) RUNNING
$tasks($task,start) $tasks($task,data)
}
}
proc next.run.queue {} {
#
# The current queue was emptied.
# Transition to the next queue if possible.
#
global run_queue tasks
set run_queue [lrange $run_queue 1 end]
if {![llength $run_queue]} {
return
}
reset.tasks
set task [lindex $tasks(list) 0]
possibly.start.task $task
after 1 [list start.task $tasks($task) [lindex $run_queue 0]]
}
proc find.next.task.sequential {task algorithm end queue_var} {
if {!$end} {
return $task
}
global tasks
upvar $queue_var queue
#
# Remove the task from the active queue.
#
set i [lsearch -exact $queue $task]
set queue [lreplace $queue $i $i]
if {![llength $queue]} {
next.run.queue
return ""
}
#
# Start the next task
#
set task [lindex $queue $i]
possibly.start.task $task
return $task
}
proc find.next.task.alternating {task algorithm end queue_var} {
global tasks
upvar $queue_var queue
set i [lsearch -exact $queue $task]
assert {expr {$i >= 0}}
if {$end} {
set queue [lreplace $queue $i $i]
if {![llength $queue]} {
next.run.queue
return ""
}
} else {
incr i
}
if {$i >= [llength $queue]} {
set i 0
}
#puts "I:$i QUEUE LENGTH:[llength $queue]"
set task [lindex $queue $i]
possibly.start.task $task
return $task
}
proc find.next.task {task algorithm end queue_var} {
upvar $queue_var queue
#
# WARNING: This returns a result.
#
find.next.task.$algorithm $task $algorithm $end queue
}
proc run.iterator {task algorithm queue} {
global tasks
set end 0
#
# Call the iterator with the data.
#
if {![$tasks($task,iterator) $tasks($task,data)]} {
#
# We are done with this task.
#
$tasks($task,end) $tasks($task,data)
set tasks($task,state) DONE
set end 1
}
#
# Find the next available task.
#
set task [find.next.task $task $algorithm $end queue]
if {"" eq $task} {
#
# No more tasks.
#
return
}
after 1 [list run.iterator $task $algorithm $queue]
}
proc start.task {task algorithm} {
global tasks
if {"RUNNING" ne $tasks($task,state)} {
$tasks($task,start) $tasks($task,data)
set tasks($task,state) RUNNING
}
run.iterator [lindex $tasks(list) 0] $algorithm $tasks(list)
}
#### TESTS ####
#
# This implements a greeting pattern that repeats 100 times.
# The first message is "well, hello" the last is "goodbye"
#
proc greeting.start data {
set ::counter 0
puts "well, hello"
}
proc greeting.iterator data {
puts hello
incr ::counter
if {$::counter > 100} {
#end task
return 0
}
#continue
return 1
}
proc greeting.end data {
puts goodbye
}
#
# This implements a timer pattern that operates for as many seconds
# as the data member of the task array passes to the initial timer.start
# procedure. The data member is set at task creation time.
#
proc timer.start data {
set ::timer_end [expr {wide([clock seconds]) + $data}]
puts "::timer_end $::timer_end"
}
proc timer.iterator data {
puts "timer iterator: [clock seconds]"
if {[clock seconds] >= $::timer_end} {
#end task
return 0
}
#continue
return 1
}
proc timer.end data {
puts "BINGO!"
}
task greeting.start greeting.iterator greeting.end {}
task timer.start timer.iterator timer.end 2
foreach t [list sequential alternating sequential alternating alternating sequential] {
run.tasks $t
}
catch {vwait forever}
======
----
See also: [Concurrency concepts]
<<categories>> Concurrency} regexp2} CALL {my render {After Task Scheduler} {[George Peter Staplin]: As a fun experiment with cooperative task scheduling I implemented this prototype.
----
# By George Peter Staplin -- Dec 19, 2005 - Jan 5, 2006
# This implements a task scheduler using [after].
# It supports (so far) 2 scheduling algorithms -- alternating and sequential.
# This is version 4 of a prototype.
array set ::tasks {}
set ::task_counter 0
set ::run_queue [list]
proc assert body {
if {![uplevel 1 $body]} {
return -code error "assertion failed: $body"
}
}
proc task {start iterator end data} {
global tasks task_counter
incr task_counter
while {[info exists tasks($task_counter)]} {
incr task_counter
}
lappend tasks(list) $task_counter
set tasks($task_counter) $task_counter
#
# The valid states are NOT_RUNNING, RUNNING, DONE.
#
set tasks($task_counter,state) NOT_RUNNING
set tasks($task_counter,start) $start
set tasks($task_counter,iterator) $iterator
set tasks($task_counter,end) $end
set tasks($task_counter,data) $data
return $task_counter
}
proc reset.tasks {} {
global tasks
foreach t $tasks(list) {
set tasks($t,state) NOT_RUNNING
}
}
proc run.tasks algorithm {
global tasks
global run_queue
lappend run_queue $algorithm
if {[llength $run_queue] > 1} {
#
# We will handle this after the current task queue finishes.
#
return
}
switch -- $algorithm {
sequential - alternating {}
default {
return -code error "invalid scheduler algorithm"
}
}
after 1 start.task $tasks([lindex $tasks(list) 0]) $algorithm
}
proc possibly.start.task task {
global tasks
#
# This is used to prevent starting a task multiple times.
#
if {"RUNNING" ne $tasks($task,state)} {
set tasks($task,state) RUNNING
$tasks($task,start) $tasks($task,data)
}
}
proc next.run.queue {} {
#
# The current queue was emptied.
# Transition to the next queue if possible.
#
global run_queue tasks
set run_queue [lrange $run_queue 1 end]
if {![llength $run_queue]} {
return
}
reset.tasks
set task [lindex $tasks(list) 0]
possibly.start.task $task
after 1 [list start.task $tasks($task) [lindex $run_queue 0]]
}
proc find.next.task.sequential {task algorithm end queue_var} {
if {!$end} {
return $task
}
global tasks
upvar $queue_var queue
#
# Remove the task from the active queue.
#
set i [lsearch -exact $queue $task]
set queue [lreplace $queue $i $i]
if {![llength $queue]} {
next.run.queue
return ""
}
#
# Start the next task
#
set task [lindex $queue $i]
possibly.start.task $task
return $task
}
proc find.next.task.alternating {task algorithm end queue_var} {
global tasks
upvar $queue_var queue
set i [lsearch -exact $queue $task]
assert {expr {$i >= 0}}
if {$end} {
set queue [lreplace $queue $i $i]
if {![llength $queue]} {
next.run.queue
return ""
}
} else {
incr i
}
if {$i >= [llength $queue]} {
set i 0
}
#puts "I:$i QUEUE LENGTH:[llength $queue]"
set task [lindex $queue $i]
possibly.start.task $task
return $task
}
proc find.next.task {task algorithm end queue_var} {
upvar $queue_var queue
#
# WARNING: This returns a result.
#
find.next.task.$algorithm $task $algorithm $end queue
}
proc run.iterator {task algorithm queue} {
global tasks
set end 0
#
# Call the iterator with the data.
#
if {![$tasks($task,iterator) $tasks($task,data)]} {
#
# We are done with this task.
#
$tasks($task,end) $tasks($task,data)
set tasks($task,state) DONE
set end 1
}
#
# Find the next available task.
#
set task [find.next.task $task $algorithm $end queue]
if {"" eq $task} {
#
# No more tasks.
#
return
}
after 1 [list run.iterator $task $algorithm $queue]
}
proc start.task {task algorithm} {
global tasks
if {"RUNNING" ne $tasks($task,state)} {
$tasks($task,start) $tasks($task,data)
set tasks($task,state) RUNNING
}
run.iterator [lindex $tasks(list) 0] $algorithm $tasks(list)
}
#### TESTS ####
#
# This implements a greeting pattern that repeats 100 times.
# The first message is "well, hello" the last is "goodbye"
#
proc greeting.start data {
set ::counter 0
puts "well, hello"
}
proc greeting.iterator data {
puts hello
incr ::counter
if {$::counter > 100} {
#end task
return 0
}
#continue
return 1
}
proc greeting.end data {
puts goodbye
}
#
# This implements a timer pattern that operates for as many seconds
# as the data member of the task array passes to the initial timer.start
# procedure. The data member is set at task creation time.
#
proc timer.start data {
set ::timer_end [expr {wide([clock seconds]) + $data}]
puts "::timer_end $::timer_end"
}
proc timer.iterator data {
puts "timer iterator: [clock seconds]"
if {[clock seconds] >= $::timer_end} {
#end task
return 0
}
#continue
return 1
}
proc timer.end data {
puts "BINGO!"
}
task greeting.start greeting.iterator greeting.end {}
task timer.start timer.iterator timer.end 2
foreach t [list sequential alternating sequential alternating alternating sequential] {
run.tasks $t
}
catch {vwait forever}
======
----
See also: [Concurrency concepts]
<<categories>> Concurrency}} CALL {my revision {After Task Scheduler}} CALL {::oo::Obj1620851 process revision/After+Task+Scheduler} CALL {::oo::Obj1620849 process}
-errorcode
NONE
-errorinfo
Unknow state transition: LINE -> END
while executing
"error $msg"
(class "::Wiki" method "render_wikit" line 6)
invoked from within
"my render_$default_markup $N $C $mkup_rendering_engine"
(class "::Wiki" method "render" line 8)
invoked from within
"my render $name $C"
(class "::Wiki" method "revision" line 31)
invoked from within
"my revision $page"
(class "::Wiki" method "process" line 56)
invoked from within
"$server process [string trim $uri /]"
-errorline
4