A variant of SF patch 103028 (Make tempfile.mktemp threadsafe).

Tested on Windows.  Should be tested on Linux.  Should also be
tested on some platform without threads (I simulated that by
making the "import thread" fail, but that's not the same as
actually doing it!).
This commit is contained in:
Tim Peters 2001-01-12 10:02:46 +00:00
parent 264630e855
commit 1baa22aff0
1 changed files with 45 additions and 12 deletions

View File

@ -4,16 +4,12 @@
# how to choose a temp directory or filename on MS-DOS or other # how to choose a temp directory or filename on MS-DOS or other
# systems so it may have to be changed... # systems so it may have to be changed...
import os import os
# Parameters that the caller may set to override the defaults # Parameters that the caller may set to override the defaults
tempdir = None tempdir = None
template = None template = None
def gettempdir(): def gettempdir():
"""Function to calculate the directory to use.""" """Function to calculate the directory to use."""
global tempdir global tempdir
@ -92,19 +88,13 @@ def gettempprefix():
return template return template
# Counter for generating unique names
counter = 0
def mktemp(suffix=""): def mktemp(suffix=""):
"""User-callable function to return a unique temporary file name.""" """User-callable function to return a unique temporary file name."""
global counter
dir = gettempdir() dir = gettempdir()
pre = gettempprefix() pre = gettempprefix()
while 1: while 1:
counter = counter + 1 i = _counter.get_next()
file = os.path.join(dir, pre + `counter` + suffix) file = os.path.join(dir, pre + str(i) + suffix)
if not os.path.exists(file): if not os.path.exists(file):
return file return file
@ -152,3 +142,46 @@ def TemporaryFile(mode='w+b', bufsize=-1, suffix=""):
# Non-unix -- can't unlink file that's still open, use wrapper # Non-unix -- can't unlink file that's still open, use wrapper
file = open(name, mode, bufsize) file = open(name, mode, bufsize)
return TemporaryFileWrapper(file, name) return TemporaryFileWrapper(file, name)
# In order to generate unique names, mktemp() uses _counter.get_next().
# This returns a unique integer on each call, in a threadsafe way (i.e.,
# multiple threads will never see the same integer). The integer will
# usually be a Python int, but if _counter.get_next() is called often
# enough, it will become a Python long.
# Note that the only name that survives this next block of code
# is "_counter".
class _ThreadSafeCounter:
def __init__(self, mutex, initialvalue=0):
self.mutex = mutex
self.i = initialvalue
def get_next(self):
self.mutex.acquire()
result = self.i
try:
newi = result + 1
except OverflowError:
newi = long(result) + 1
self.i = newi
self.mutex.release()
return result
try:
import thread
except ImportError:
class _DummyMutex:
def acquire(self):
pass
release = acquire
_counter = _ThreadSafeCounter(_DummyMutex())
del _DummyMutex
else:
_counter = _ThreadSafeCounter(thread.allocate_lock())
del thread
del _ThreadSafeCounter