I am in need of semaphores. I want to synchronize resource access
between several processes where one process writes and several other
reads that resource.
Is there a semaphore extension already existing? (searched long
without any success)
Thanks,
Milad
You can compile AOLserver (using your version of Tcl) and then use
nstclsh instead of tclsh.
What you get are several new primitives: ns_mutex, ns_sema, ns_cond,
but most important:
ns_rwlock: http://rmadilo.com/files/nsapi/ns_rwlock.html
But you also might check if the threads package includes this
primitive. I've never used a rw lock. The reason is that it is much
easier to have the writer write to a temp file and then do an atomic
rename. This has the advantage that the time required to write is
eliminated as well as many other complications. But if your OS does
not support atomic rename, you must use a read-write lock and control
all access to the file, making sure everyone uses the rw lock.
Also, just as a general statement, it is very difficult to find a use
case for semaphores. I tried, but they usually end up inside something
bigger like a read-write lock.
But if you really want to be safe and allow reading/writing of the
same file at the same time, use an atomic rename.
Here is a link to an example which uses a mutex, but also an atomic
rename:
Just the lock/rename:
set LockID [lock $store]
if {[catch {
set FD [open ${dataFileroot}.tmp w+]
fconfigure $FD -translation binary -encoding binary
puts $FD "$out"
close $FD
file rename -force ${dataFileroot}.tmp $dataFileroot
} err ]} {
unlock $store $LockID ;# Note: FD will be closed automatically, if
open
error $err "::tnt::datastore::save error saving store $store"
}
unlock $store $LockID
Also note that the lock covers many potential files, $store is an sha1
hash and the lock is determined by the last few chars of the hex rep
(usually just the last char), so the lock is almost like a reverse
semaphore: many files, one reader/writer. Deadlocks are avoided
because reads and writes do not contain recursive code (which is easy
to audit).
The thread package does include read-write locks.
> But if your OS does not support atomic rename, you must use a
> read-write lock and control all access to the file, making sure
> everyone uses the rw lock.
Is there an OS without atomic renames of files within the same
directory? Even Windows has got that right for a long time now.
(Moving between filesystems is something else.) For goodness' sake,
even networked filesystems get it right (it's one of the few atomic
operations that they do get right - along with open() with O_CREAT|
O_EXCL flags - because it is a single message each way).
Donal.
Yeah, too bad the OP said "resource" and not file. But I can't think
of a non-file resource which could use a rw lock.
If the resource is an array available to all threads, use the thread
package and the tsv arrays. They use mutex buckets, multiple arrays
share some number of mutexs, probably a hash of the array name.
Works really well.
Come to think of it, it seems the thread package would be required to
create the issue to begin with. If you only have one thread I'm not
sure how you could ever create the need to synchronize access to
anything in Tcl.
I am assuming that you are running several seperate processes and want
to co-ordinate their access to some shared resource rather than having
multiple threads inside a single process.
>
> Is there a semaphore extension already existing? (searched long
> without any success)
I'm not aware of any single extension that does exactly what you want;
however depending on the platform that you are running on these are
the options I am aware of. On Windows the TWAPI package provides
access to the OS Mutex and Semaphore commands (see the Win32 Raw API
documentation). On Unix I'm not aware of any package that wraps the
IPC comamnds (this does not mean that there isn't one) so you may have
to create your own. The issue I always have with Unix IPC is that the
resources don't get cleaned up when a process terminates unexpectedly.
I often use file locking (fcntl) for IPC if simple mutex functionality
is all that is required; file locks get released when the process
holding them terminates.
The other option that you have is to re-engineer the solution so that
the problem goes away: create one or more server processes that are
resposnible for the shared resources and use sockets or the comm
package or some other mechanism to allow the clients to access the
resources. Of course this may not be possible which will bring you
back to sempahores :-)
>
> Thanks,
> Milad