$Header: /cvsroot/aolserver/aolserver.com/docs/devel/tcl/api/thread.html,v 1.2 2002/03/19 20:30:11 kriston Exp $
ns_cond broadcast wakes up all threads waiting on the specified event. The eventid argument is the event ID returned by ns_cond create when the event was created.
ns_cond create initializes an event and returns an event ID for the new event.
ns_cond destroy frees the resources associated with the specified event. The eventid argument is the event ID returned by ns_cond create when the event was created.
ns_cond set wakes up the specified event. The eventid argument is the event ID returned by ns_cond create when the event was created.
ns_cond wait waits for the specified event for a specified time. The eventid argument is the event ID returned by ns_cond create when the event was created. The lockid argument is the id of a mutex lock. The timeout argument is the time to wait in seconds. The return value is 0 (zero) if the event timed out and 1(one) if the event was woken up.
ns_critsec create creates a critical section and returns a critical section ID.
ns_critsec destroy destroys the specified critical section. The csid argument is the critical section ID returned by ns_critsec create when the critical section was created.
ns_critsec enter enters the specified critical section. The csid argument is the critical section ID returned by ns_critsec create when the critical section was created.
ns_critsec leave leaves the specified critical section. The csid argument is the critical section ID returned by ns_critsec create when the critical section was created.
ns_event create initializes an event and returns an event ID for the new event.
ns_event destroy frees the resources associated with the specified event. The eventid argument is the event ID returned by ns_event create when the event was created.
ns_event set wakes up the specified event. The eventid argument is the event ID returned by ns_event create when the event was created.
ns_event wait waits for the specified event for a specified time. The eventid argument is the event ID returned by ns_event create when the event was created. The lockid argument is the id of a mutex lock. The timeout argument is the time to wait in seconds. The return value is 0 (zero) if the event timed out and 1(one) if the event was woken up.
ns_mutex destroy frees the resources associated with the specified mutual exclusion lock. The mutexid argument is the mutex ID returned by ns_mutex create when the mutex was created.
ns_mutex lock acquires the specified mutual exclusion lock. The mutexid argument is the mutex ID returned by ns_mutex create when the mutex was created.
ns_mutex unlock unlocks the specified mutual exclusion lock. The mutexid argument is the mutex ID returned by ns_mutex create when the mutex was created.
ns_share Shared set Shared(file) [open myfile.data] set Shared(lock) [ns_mutex create] detach $Shared(file)Later (for example, in a request procedure), access the data file:
ns_share Shared ns_mutex lock $Shared(lock) catch { ... access $Shared(file) ... } ns_mutex unlock $Shared(lock)Note: The "catch" is important so the lock isn't held if Tcl unwinds due to an error accessing the file.
At shutdown (for example, in your shutdown procedure registered with ns_atshutdown), close the file and destroy the lock:
ns_share Shared close $Shared(file) ns_mutex destroy $Shared(lock)
Try to avoid ns_share whenever possible. The lock contention will kill your server's performance. Investigate using the nsv commands instead to share data among multiple interpreters and multiple threads.
ns_rwlock destroy frees the resources associated with the specified read/write lock. The rwlockid argument is the read/write lock ID returned by ns_rwlock create when the lock was created.
ns_rwlock readlock acquires a read lock. Any number of read locks can be pending. If there's a write lock active, the read lock acquisition blocks until the write lock is released.
ns_rwlock readunlock releases a read lock.
ns_rwlock writelock acquires a write lock. Only one write lock can be in effect. If there are pending read locks active, the write lock acquisition blocks until all of the read locks drain. If a subsequent read lock acquisition attempt is made, the write lock has priority.
ns_rwlock writeunlock releases a write lock
About Read/Write Locks
Read/write locks are a serialization mechanism for using data structures where multiple reads can happen simultaneously, but where writes must happen singly. For example, suppose you have a hash table that is heavily used but doesn't change very often. You'd like to have multiple threads be able to read from the table without blocking on each other, but when you need to update the table, you can do so safely without having to worry about other threads reading incorrect data.
The principal feature of read/write locks is the mechanism of which locks have priority and which locks must wait. Any number of read locks can be pending. If there's a write lock active, the read lock acquisition blocks until the write lock is released. Also, only one write lock can be in effect. If there are pending read locks active, the write lock acquisition blocks until all of the read locks drain. If a subsequent read lock acquisition attempt is made while a write lock is waiting to acquire, the write lock has priority.
ns_sema destroy frees the resources associated with the specified semaphore. The semaid argument is the ID returned by ns_sema create when the semaphore was created.
ns_sema release increments the count of the specified semaphore. By default, the semaphore is incremented 1 (one) time. If the count argument is specified, the semaphore is incremented count times. The semaid argument is the ID returned by ns_sema create when the semaphore was created.
ns_sema wait waits for the count of the specified semaphore to be greater than 0 (zero). If it is greater than 0, the count is decremented and processing continues. If it is not greater than 0, it is blocked until this is possible. The semaid argument is the ID returned by ns_sema create when the semaphore was created.
ns_thread begindetached begins a detached thread that doesn't have to be (and can't be) waited for.
ns_thread get gets the thread ID of the current thread. The result is a thread ID that can be passed to ns_thread wait and may look something like "tid532".
ns_thread getid gets the thread integer number for the current thread. The result is a small integer used for identifying threads is a human-readable way, such as "1" or "1120", for example.
ns_thread wait waits for the specified thread to exit. The tid argument is a thread ID returned by ns_thread begin or ns_thread get.
ns_thread yield causes the current thread to yield.
# This is the procedure which is evaluated for each thread and # handles a single connection to host number $i proc getpage {i} { global pages # new thread will start here - first connect to host set host [format "www%2d.foo.com" $i] set fds [ns_sockopen $host 80 set r [lindex $fds 0] set w [lindex $fds 1] # next, send request puts $w "GET /index.htm HTTP/1.0\r\n\r" flush $w # then read page set pages($i) [read $r] # and close sockets close $w close $r # thread goes away here and other threads waiting # on ns_thread wait will wakeup } # Here's the loop which creates the threads which run getpage. for {set i 1} {$i < 9} {incr i} { set tids($i) [ns_thread begin "getpage $i"] } # wait for the threads to exit and then process the pages for {set i 1} {$i < 9} {incr i} { ns_thread wait $tids($i) # output page ... process the page in $pages($i) put there by other thread ... }
Note that the code here is much simpler to follow than the ns_sockselect example; that's the benefit of multithreaded programming. However, it uses more resources as threads need to be created and initialized. This can be a problem if you plan to create many threads.
"entries: # flushed: # hits: # misses: # hitrate: #"
If an arrayvar is specified, this fills the array with the elements: entries, flushed, hits, misses, and hitrates. The entries are populated with their corresponding values.
See the nstelemetry.adp utility for an example of how ns_cache_stats is used.
proc show_at_close { } { set tmpfile [ns_tmpnam] # open tmpfile, write stuff to it and close it ns_atclose "ns_unlink -nocomplain $tmpfile" return $tmpfile } ;# show_at_close
proc theLastThing {} { global Shared close $Shared(file) ns_mutex destroy $Shared(lock) } ... ns_atshutdown theLastThing ...
proc dosomething blah { ns_log Notice "proc with arg '$blah'" } ns_atsignal dosomething $arg1
Specify -thread if you want a thread created to run the procedure. This will allow the scheduler to continue with other scheduled procedures. Specifying -thread is appropriate in situations where the script will not return immediately, such as when the script performs network activity.
Specify -once if you want the script to run only one time. The default is that the script will be re-scheduled after each time it is run.
ns_schedule_daily returns an id number for the scheduled procedure that is needed to stop the scheduled procedure with ns_unschedule_proc.
# Script to roll and rcp log file to host "grinder" proc rolllog {} { set suffix [ns_strftime "%y-%m-%d"] set new [ns_accesslog file].$suffix ns_accesslog roll $new exec rcp $new grinder:/logs/[file tail $new] } # Schedule "rolllog" to run at 3:30 am each morning ns_schedule_daily -thread 3 30 rolllog
Specify -thread if you want a thread created to run the procedure. This will allow the scheduler to continue with other scheduled procedures. Specifying -thread is appropriate in situations where the script will not return immediately, such as when the script performs network activity.
Specify -once if you want the script to run only one time. The default is that the script will be re-scheduled after each time it is run.
ns_schedule_proc returns an id number for the scheduled procedure that is needed to stop the scheduled procedure with ns_unschedule_proc.
proc dosomething blah { ns_log Notice "proc with arg '$blah'" } ns_schedule_proc 10 dosomething $arg1
Specify -thread if you want a thread created to run the procedure. This will allow the scheduler to continue with other scheduled procedures. Specifying -thread is appropriate in situations where the script will not return immediately, such as when the script performs network activity.
Specify -once if you want the script to run only one time. The default is that the script will be re-scheduled after each time it is run.
ns_schedule_weekly returns an id number for the scheduled procedure that is needed to stop the scheduled procedure with ns_unschedule_proc.