Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(24)

Side by Side Diff: Lib/multiprocessing/heap.py

Issue 10639: reindent.py converts newlines to platform default
Patch Set: Created 8 years, 8 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Lib/multiprocessing/connection.py ('k') | Lib/multiprocessing/process.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # 1 #
2 # Module which supports allocation of memory from an mmap 2 # Module which supports allocation of memory from an mmap
3 # 3 #
4 # multiprocessing/heap.py 4 # multiprocessing/heap.py
5 # 5 #
6 # Copyright (c) 2006-2008, R Oudkerk 6 # Copyright (c) 2006-2008, R Oudkerk
7 # All rights reserved. 7 # All rights reserved.
8 # 8 #
9 # Redistribution and use in source and binary forms, with or without 9 # Redistribution and use in source and binary forms, with or without
10 # modification, are permitted provided that the following conditions 10 # modification, are permitted provided that the following conditions
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
94 def __init__(self, size=mmap.PAGESIZE): 94 def __init__(self, size=mmap.PAGESIZE):
95 self._lastpid = os.getpid() 95 self._lastpid = os.getpid()
96 self._lock = threading.Lock() 96 self._lock = threading.Lock()
97 self._size = size 97 self._size = size
98 self._lengths = [] 98 self._lengths = []
99 self._len_to_seq = {} 99 self._len_to_seq = {}
100 self._start_to_block = {} 100 self._start_to_block = {}
101 self._stop_to_block = {} 101 self._stop_to_block = {}
102 self._allocated_blocks = set() 102 self._allocated_blocks = set()
103 self._arenas = [] 103 self._arenas = []
104 # list of pending blocks to free - see free() comment below
105 self._pending_free_blocks = []
106 104
107 @staticmethod 105 @staticmethod
108 def _roundup(n, alignment): 106 def _roundup(n, alignment):
109 # alignment must be a power of 2 107 # alignment must be a power of 2
110 mask = alignment - 1 108 mask = alignment - 1
111 return (n + mask) & ~mask 109 return (n + mask) & ~mask
112 110
113 def _malloc(self, size): 111 def _malloc(self, size):
114 # returns a large enough block -- it might be much larger 112 # returns a large enough block -- it might be much larger
115 i = bisect.bisect_left(self._lengths, size) 113 i = bisect.bisect_left(self._lengths, size)
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 168
171 length = stop - start 169 length = stop - start
172 seq = self._len_to_seq[length] 170 seq = self._len_to_seq[length]
173 seq.remove(block) 171 seq.remove(block)
174 if not seq: 172 if not seq:
175 del self._len_to_seq[length] 173 del self._len_to_seq[length]
176 self._lengths.remove(length) 174 self._lengths.remove(length)
177 175
178 return start, stop 176 return start, stop
179 177
180 def _free_pending_blocks(self): 178 def free(self, block):
181 # Free all the blocks in the pending list - called with the lock held. 179 # free a block returned by malloc()
182 while True: 180 assert os.getpid() == self._lastpid
183 try: 181 self._lock.acquire()
184 block = self._pending_free_blocks.pop() 182 try:
185 except IndexError:
186 break
187 self._allocated_blocks.remove(block) 183 self._allocated_blocks.remove(block)
188 self._free(block) 184 self._free(block)
189 185 finally:
190 def free(self, block): 186 self._lock.release()
191 # 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).
200 assert os.getpid() == self._lastpid
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()
213 187
214 def malloc(self, size): 188 def malloc(self, size):
215 # return a block of right size (possibly rounded up) 189 # return a block of right size (possibly rounded up)
216 assert 0 <= size < sys.maxsize 190 assert 0 <= size < sys.maxsize
217 if os.getpid() != self._lastpid: 191 if os.getpid() != self._lastpid:
218 self.__init__() # reinitialize after fork 192 self.__init__() # reinitialize after fork
219 self._lock.acquire() 193 self._lock.acquire()
220 self._free_pending_blocks()
221 try: 194 try:
222 size = self._roundup(max(size,1), self._alignment) 195 size = self._roundup(max(size,1), self._alignment)
223 (arena, start, stop) = self._malloc(size) 196 (arena, start, stop) = self._malloc(size)
224 new_stop = start + size 197 new_stop = start + size
225 if new_stop < stop: 198 if new_stop < stop:
226 self._free((arena, new_stop, stop)) 199 self._free((arena, new_stop, stop))
227 block = (arena, start, new_stop) 200 block = (arena, start, new_stop)
228 self._allocated_blocks.add(block) 201 self._allocated_blocks.add(block)
229 return block 202 return block
230 finally: 203 finally:
(...skipping 14 matching lines...) Expand all
245 Finalize(self, BufferWrapper._heap.free, args=(block,)) 218 Finalize(self, BufferWrapper._heap.free, args=(block,))
246 219
247 def get_address(self): 220 def get_address(self):
248 (arena, start, stop), size = self._state 221 (arena, start, stop), size = self._state
249 address, length = _multiprocessing.address_of_buffer(arena.buffer) 222 address, length = _multiprocessing.address_of_buffer(arena.buffer)
250 assert size <= length 223 assert size <= length
251 return address + start 224 return address + start
252 225
253 def get_size(self): 226 def get_size(self):
254 return self._state[1] 227 return self._state[1]
OLDNEW
« no previous file with comments | « Lib/multiprocessing/connection.py ('k') | Lib/multiprocessing/process.py » ('j') | no next file with comments »

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+