diff options
author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-09-12 14:16:22 +0000 |
---|---|---|
committer | <> | 2014-10-24 11:04:40 +0000 |
commit | a77e3a63f004e6ee789fa05e4a5bbc333b1529f1 (patch) | |
tree | efe8a68996c19b7b0765ebc689937721d1d99cf7 /demo/premise.py | |
download | sysv-ipc-tarball-master.tar.gz |
Imported from /home/lorry/working-area/delta_python-packages_sysv-ipc-tarball/sysv_ipc-0.6.8.tar.gz.HEADsysv_ipc-0.6.8master
Diffstat (limited to 'demo/premise.py')
-rwxr-xr-x | demo/premise.py | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/demo/premise.py b/demo/premise.py new file mode 100755 index 0000000..98dd30c --- /dev/null +++ b/demo/premise.py @@ -0,0 +1,106 @@ +# Python modules +import time +import os +import sys +PY_MAJOR_VERSION = sys.version_info[0] +# hashlib is only available in Python >= 2.5. I still want to support +# older Pythons so I import md5 if hashlib is not available. Fortunately +# md5 can masquerade as hashlib for my purposes. +try: + import hashlib +except ImportError: + import md5 as hashlib + +# 3rd party modules +import sysv_ipc + +# Utils for this demo +import utils +if PY_MAJOR_VERSION > 2: + import utils_for_3 as flex_utils +else: + import utils_for_2 as flex_utils + +utils.say("Oooo 'ello, I'm Mrs. Premise!") + +params = utils.read_params() + +# Create the semaphore & shared memory. I read somewhere that semaphores +# and shared memory have separate key spaces, so one can safely use the +# same key for each. This seems to be true in my experience. + +# For purposes of simplicity, this demo code makes no allowance for the +# failure of the semaphore or memory constructors. This is unrealistic +# because one can never predict whether or not a given key will be available, +# so your code must *always* be prepared for these functions to fail. + +semaphore = sysv_ipc.Semaphore(params["KEY"], sysv_ipc.IPC_CREX) +memory = sysv_ipc.SharedMemory(params["KEY"], sysv_ipc.IPC_CREX) + +# I seed the shared memory with a random value which is the current time. +what_i_wrote = time.asctime() +s = what_i_wrote + +utils.write_to_memory(memory, what_i_wrote) + +for i in range(0, params["ITERATIONS"]): + utils.say("iteration %d" % i) + if not params["LIVE_DANGEROUSLY"]: + # Releasing the semaphore... + utils.say("releasing the semaphore") + semaphore.release() + # ...and wait for it to become available again. In real code it'd be + # wise to sleep briefly before calling .acquire() in order to be + # polite and give other processes an opportunity to grab the semaphore + # while it is free and thereby avoid starvation. But this code is meant + # to be a stress test that maximizes the opportunity for shared memory + # corruption, and politeness has no place in that. + utils.say("acquiring the semaphore...") + semaphore.acquire() + + s = utils.read_from_memory(memory) + + # I keep checking the shared memory until something new has been written. + while s == what_i_wrote: + if not params["LIVE_DANGEROUSLY"]: + utils.say("releasing the semaphore") + semaphore.release() + utils.say("acquiring the semaphore...") + semaphore.acquire() + + # Once the call to .acquire() completes, I own the shared resource and + # I'm free to read from the memory. + s = utils.read_from_memory(memory) + + # What I read must be the md5 of what I wrote or something's gone wrong. + if PY_MAJOR_VERSION > 2: + what_i_wrote = what_i_wrote.encode() + + try: + assert(s == hashlib.md5(what_i_wrote).hexdigest()) + except AssertionError: + flex_utils.raise_error(AssertionError, + "Shared memory corruption after %d iterations." % i) + + # MD5 the reply and write back to Mrs. Conclusion. + if PY_MAJOR_VERSION > 2: + s = s.encode() + what_i_wrote = hashlib.md5(s).hexdigest() + utils.write_to_memory(memory, what_i_wrote) + + +# Announce for one last time that the semaphore is free again so that +# Mrs. Conclusion can exit. +if not params["LIVE_DANGEROUSLY"]: + utils.say("Final release of the semaphore followed by a 5 second pause") + semaphore.release() + time.sleep(5) + # ...before beginning to wait until it is free again. + utils.say("Final acquisition of the semaphore") + semaphore.acquire() + +utils.say("Destroying semaphore and shared memory") +# It'd be more natural to call memory.remove() and semaphore.remove() here, +# but I'll use the module-level functions instead to demonstrate their use. +sysv_ipc.remove_shared_memory(memory.id) +sysv_ipc.remove_semaphore(semaphore.id) |