1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
#
# This module was written in 2007 by S James S Stapleton
# This module is released as PUBLIC DOMAIN
#
# Please respect the creator/author's intent and release all
# modifications as public domain. Thank you.
#
from time import time
from time import sleep
import weakref
import inheritable
import lockholder
class Srlock(inheritable.Irlock):
"""
This is a basic wrapper of the the lock object, that defines an sacquire and srelease function pair. Rather than returning true or
false, the return they return the lockholder type the class was initialized with (greedy or efficient, efficient is the default.)
This also defines a gacquire and eacquire function function, each of which provides a greedy or efficient timeout method.
"""
__holder_type = None
__sleeptime = None
__minchecks = None
def __init__(self, holder_type=lockholder.SlockE, sleeptime=0.10, minchecks=5):
"""
Initialization:
holder_type: The Slock[G|E] to act as a lock holder for saquire. lockholder.SlockE is the default. It will sleep between lock
attempts. the G variant does not auto-sleep itself. Either G or E class can fill this argument, or a defined
subclass (useful for changing the defaults.
sleeptime: If eacquire is called, this will be the amount of time between lock attempts, until the timeout.
minchecks: If sleeptime does not provide enough checks during the timeout period in eacquire, this is used to create a new
sleeptime that should produce roughly maxtries attempts at the lock (it is not guranteed, especially with small
timeouts).
"""
inheritable.Irlock.__init__(self)
self.__holder_type = holder_type
self.__sleeptime = sleeptime
self.__minchecks = minchecks
#def __init__(self):
def sacquire(self, timeout=True):
"""
This works as a normal acquire, except there is a timeout period. This may have a boolean translatable value, an integer or a
float.
Integer - Time out in most timeout seconds
Float - Time out in timeout seconds
True - Block until lock is acquired
False - Nonblocking lock attempt.
This returns a lock holder rather than a lock. The lock is freed if release is called if the lockholder is destroyed, or release is
called on this object.
Due to the garbage collector, the return value should always be kept and not overwritten until after the lock is unenecessary, then
it can have it's .release() function called or be del'ed.
NOTE: only call release() on the returned object, or let it be destroyed, DO NOT CALL ON THIS LOCK if you use this function, as
this lock cannot figure out which is the associated lock holder, if any.
"""
lh = self.__holder_type(self)
test = lh.acquire(timeout)
if(test):
#record a weakref, so we can kill the holder is the thread is released.
return lh
return False
#def sacquire(self, timeout=True):
def eacquire(self, timeout=True, sleeptime=None, minchecks=None):
"""
Attempt to acquire a lock on this object in an efficient manner, using the default class mintries/sleeptime values
timeout:
int/float - block until timeout after timeout seconds
True - block
False - don't block
if the lock is acquired, true is returned, otherwise false.
if minchecks is not an integer, the class __minchecks value is used
if sleeptime is not a number, the class __sleeptime value is used.
"""
if(type(timeout) == int):
timeout = float(timeout)
if(type(timeout) == float):
stop = time() + timeout
if(type(sleeptime) != int and type(sleeptime) != float):
sleeptime = self.__sleeptime
if(type(minchecks) != int):
minchecks = self.__minchecks
#now get the sleep time, remember calcs take time too, and we would normally miss
#at least one minimum check, so we add one.
if(sleeptime < timeout/(self.__minchecks+1)):
sleeptime = timeout/(self.__minchecks+1)
while(stop-time() > 0):
if(inheritable.Irlock.acquire(self, False)):
return True
sleep(sleeptime)
#while(stop-time() > 0):
return False
return inheritable.Irlock.acquire(self, timeout)
#if(type(timeout) == int)
#def eacquire(self, timeout=True):
def gacquire(self, timeout=True):
"""
Attempt to acquire a lock on this object in a greedy manner, without putting itself to sleep. The timeout value may be int, float,
or evaluate to a boolean:
int/float - block until timeout after timeout seconds
True - block
False - don't block
if the lock is acquired, true is returned, otherwise false.
"""
if(type(timeout) == int):
timeout = float(timeout)
if(type(timeout) == float):
stop = time() + timeout
while(stop-time() > 0):
if(inheritable.Irlock.acquire(self, False)):
return True
#while(stop-time() > 0):
return False
return inheritable.Irlock.acquire(self, timeout)
#if(type(timeout) == int)
#def eacquire(self, timeout=True):
#class Slock(inheritable.Irlock):
|