For Programmers: Free Programming Magazines  


Home > Archive > Tcl > July 2007 > Running procs at timed intervals after script has completed









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Running procs at timed intervals after script has completed
bluemooseking@gmail.com

2007-07-26, 10:08 pm

Hi,

I'm trying to find a way to run a section of code at regular intervals
after a script has completed. I have embedded TCL in a C application
that launches scripts using the TCL_EvalFile. I only have a single
thread/interpreter in my application at this point. For some of my
scripts I want to be able to start a 'task' continue performing
certain tasks after the main script has completed... i.e. TCL_EvalFile
has returned to my C application, and the C application is performing
other tasks now. The problem is that the tasks seem that they have to
be performed from within the main thread, as there are external DLL
loaded and many specialized functions that are only contained in the
context of the main thread. I had thought of creating a couple of
startkicks/stopkicks procs which would launch a second task to kick
the main thread at regular intervals. The problem with the
impementation below is that although the startkicks proc seems to work
correctly, the main thread will not perform the 'dostuff' function
unless I run "thread::wait at the end of my last script, but then the
TCL_EvalFile function never returns.

Any help would be appreciated, I've been running in circles on this
one for a while now.

Jon


----------------------------------------------------
CODE SO FAR FOLLOWS BELOW:
----------------------------------------------------
package require Thread

namespace eval testbed {

variable ThreadID
variable STATEMENT

proc startkicks {} {

upvar ThreadID tid
tsv::set vars exit false
tsv::set vars main_tid [thread::id]

puts [format "EXIT: %s\n" [tsv::get vars exit]]
set tid [thread::create -joinable {

while {![tsv::get vars exit]} {


set mtid [tsv::get vars main_tid]
thread::send -async $mtid {testbed::dostuff}
#thread::send $mtid {testbed::dostuff} -async true
after 5000

}

}]
puts [format "tid: %s\n" $tid]
puts "WAITING\n"
}

proc init {} {
upvar STATEMENT line
set line "HELLO THERE... \n"
}

proc dostuff {} {

upvar STATEMENT line
puts $line
}

proc stopkicks {} {

upvar ThreadID tid
tsv::set vars exit true
puts [format "EXIT: %s\n" [tsv::get vars exit]]
puts "JOINING\n"
thread::join $tid

puts DONE\n

}

}

Helmut Giese

2007-07-26, 10:08 pm

Hi,
below you will find a small example of how to have certain
"independent" procs run after the "main task" has finished. It doesn't
need a different thread - it runs just fine in the main Tcl
interpreter.

Maybe it gives you some ideas - the easiest would be to have your
central 'TCL_EvalFile' take a file which is structured like the code
below.
HTH
Helmut Giese

PS: There are loads of variations on the 'every' idiom - check out the
wiki.
---
set runCnt 0
set stop 0

proc every {delay script} {
eval $script
after $delay [list every $delay $script]
}

proc run1 {} {
variable runCnt

puts -nonewline .
flush stdout
incr runCnt
}

proc run2 {} {
variable runCnt

puts -nonewline +
flush stdout
incr runCnt
}

proc checkStop {} {
variable runCnt
variable stop

if { $runCnt > 15 } {
# terminate - first cancel everything still pending
puts ""
foreach id [after info] {
puts "Cancelling $id"
after cancel $id
}
set stop 1
}
}

proc main {} {
puts "main starts - doing lots of work"
# simulate the main script working
after 1500
# now schedule independent procs
puts "main done - scheduling worker procs"
every 2000 run1
every 3500 run2
every 1000 checkStop
}

### start ###
main
# launch the event loop for a non-Tk app
vwait stop
puts ""
puts "Application terminating"
---

slebetman@yahoo.com

2007-07-27, 8:09 am

On Jul 27, 3:22 am, Helmut Giese <hgi...@ratiosoft.com> wrote:
> Hi,
> below you will find a small example of how to have certain
> "independent" procs run after the "main task" has finished. It doesn't
> need a different thread - it runs just fine in the main Tcl
> interpreter.
>
> Maybe it gives you some ideas - the easiest would be to have your
> central 'TCL_EvalFile' take a file which is structured like the code
> below.
> HTH
> Helmut Giese
>
> PS: There are loads of variations on the 'every' idiom - check out the
> wiki.
> ---
> set runCnt 0
> set stop 0
>
> proc every {delay script} {
> eval $script
> after $delay [list every $delay $script]
>
> }
>
> proc run1 {} {
> variable runCnt
>
> puts -nonewline .
> flush stdout
> incr runCnt
>
> }
>
> proc run2 {} {
> variable runCnt
>
> puts -nonewline +
> flush stdout
> incr runCnt
>
> }
>
> proc checkStop {} {
> variable runCnt
> variable stop
>
> if { $runCnt > 15 } {
> # terminate - first cancel everything still pending
> puts ""
> foreach id [after info] {
> puts "Cancelling $id"
> after cancel $id
> }
> set stop 1
> }
>
> }
>
> proc main {} {
> puts "main starts - doing lots of work"
> # simulate the main script working
> after 1500
> # now schedule independent procs
> puts "main done - scheduling worker procs"
> every 2000 run1
> every 3500 run2
> every 1000 checkStop
>
> }
>
> ### start ###
> main
> # launch the event loop for a non-Tk app
> vwait stop
> puts ""
> puts "Application terminating"
> ---


Note that this doesn't solve the problem. It has the same drawback as
before: TCL_EvalFile doesn't return and your application hangs. The
proper way to handle this is to correctly implement the event loop and
have your application structured around it. Then you can use the trick
above or your original idea with threads to do it.

Take a look at the source for tclsh or wish to see how it's done.
Better yet, take the source for tclsh or wish and modify it to merge
with your custom C application. (Even better would be to make your C
application a lodable C library, via Swig for example, and call it
from within Tcl).

bluemooseking@gmail.com

2007-07-27, 7:10 pm

What would be a good way to implement the event loop? I've been
thinking in my head of executing TCL_Eval(my_interp,"thread::wait")
after the completion of TCL_EvalFile... but then what do I replace
TCL_EvalFile with to ensure the next script still runs? Is it
TCL_QueueEvent?

>
> Note that this doesn't solve the problem. It has the same drawback as
> before: TCL_EvalFile doesn't return and your application hangs. The
> proper way to handle this is to correctly implement the event loop and
> have your application structured around it. Then you can use the trick
> above or your original idea with threads to do it.
>
> Take a look at the source for tclsh or wish to see how it's done.
> Better yet, take the source for tclsh or wish and modify it to merge
> with your custom C application. (Even better would be to make your C
> application a lodable C library, via Swig for example, and call it
> from within Tcl).



Ron Fox

2007-07-27, 7:10 pm

See Tcl_DoOneEvent

Call that from time to time in your C app... with the TCL_DONT_WAIT
flag set so that you get control back right away if there are no
events to process.

RF

bluemooseking@gmail.com wrote:
> What would be a good way to implement the event loop? I've been
> thinking in my head of executing TCL_Eval(my_interp,"thread::wait")
> after the completion of TCL_EvalFile... but then what do I replace
> TCL_EvalFile with to ensure the next script still runs? Is it
> TCL_QueueEvent?
>
>
>

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com