Ignore:
Timestamp:
Mar 19, 2014, 11:31:01 PM (11 years ago)
Author:
dmik
Message:

python: Merge vendor 2.7.6 to trunk.

Location:
python/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • python/trunk

  • python/trunk/Lib/multiprocessing/heap.py

    r2 r391  
    44# multiprocessing/heap.py
    55#
    6 # Copyright (c) 2007-2008, R Oudkerk --- see COPYING.txt
     6# Copyright (c) 2006-2008, R Oudkerk
     7# All rights reserved.
     8#
     9# Redistribution and use in source and binary forms, with or without
     10# modification, are permitted provided that the following conditions
     11# are met:
     12#
     13# 1. Redistributions of source code must retain the above copyright
     14#    notice, this list of conditions and the following disclaimer.
     15# 2. Redistributions in binary form must reproduce the above copyright
     16#    notice, this list of conditions and the following disclaimer in the
     17#    documentation and/or other materials provided with the distribution.
     18# 3. Neither the name of author nor the names of any contributors may be
     19#    used to endorse or promote products derived from this software
     20#    without specific prior written permission.
     21#
     22# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
     23# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     26# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32# SUCH DAMAGE.
    733#
    834
     
    2753if sys.platform == 'win32':
    2854
    29     from ._multiprocessing import win32
     55    from _multiprocessing import win32
    3056
    3157    class Arena(object):
     
    76102        self._allocated_blocks = set()
    77103        self._arenas = []
     104        # list of pending blocks to free - see free() comment below
     105        self._pending_free_blocks = []
    78106
    79107    @staticmethod
     
    150178        return start, stop
    151179
     180    def _free_pending_blocks(self):
     181        # Free all the blocks in the pending list - called with the lock held.
     182        while True:
     183            try:
     184                block = self._pending_free_blocks.pop()
     185            except IndexError:
     186                break
     187            self._allocated_blocks.remove(block)
     188            self._free(block)
     189
    152190    def free(self, block):
    153191        # free a block returned by malloc()
     192        # Since free() can be called asynchronously by the GC, it could happen
     193        # that it's called while self._lock is held: in that case,
     194        # self._lock.acquire() would deadlock (issue #12352). To avoid that, a
     195        # trylock is used instead, and if the lock can't be acquired
     196        # immediately, the block is added to a list of blocks to be freed
     197        # synchronously sometimes later from malloc() or free(), by calling
     198        # _free_pending_blocks() (appending and retrieving from a list is not
     199        # strictly thread-safe but under cPython it's atomic thanks to the GIL).
    154200        assert os.getpid() == self._lastpid
    155         self._lock.acquire()
    156         try:
    157             self._allocated_blocks.remove(block)
    158             self._free(block)
    159         finally:
    160             self._lock.release()
     201        if not self._lock.acquire(False):
     202            # can't acquire the lock right now, add the block to the list of
     203            # pending blocks to free
     204            self._pending_free_blocks.append(block)
     205        else:
     206            # we hold the lock
     207            try:
     208                self._free_pending_blocks()
     209                self._allocated_blocks.remove(block)
     210                self._free(block)
     211            finally:
     212                self._lock.release()
    161213
    162214    def malloc(self, size):
     
    166218            self.__init__()                     # reinitialize after fork
    167219        self._lock.acquire()
     220        self._free_pending_blocks()
    168221        try:
    169222            size = self._roundup(max(size,1), self._alignment)
Note: See TracChangeset for help on using the changeset viewer.