Skip to content

Commit

Permalink
Merge pull request #76 from freininghaus/fix-issue-75-out-of-memory
Browse files Browse the repository at this point in the history
Use WeakKeyDictionary for caching types in is_future_like
  • Loading branch information
syrusakbary committed Dec 18, 2019
2 parents 729c35a + cf4316e commit d99384f
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 2 deletions.
1 change: 0 additions & 1 deletion promise/dataloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@ def __init__(
self.cache = cache

self.get_cache_key = get_cache_key or (lambda x: x)

self._promise_cache = cache_map or {}
self._queue = [] # type: List[Loader]
self._scheduler = scheduler
Expand Down
4 changes: 3 additions & 1 deletion promise/promise.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from sys import version_info, exc_info
from threading import RLock
from types import TracebackType
from weakref import WeakKeyDictionary

from six import reraise # type: ignore
from .async_ import Async
Expand Down Expand Up @@ -34,6 +35,7 @@
Union,
Generic,
Hashable,
MutableMapping,
)


Expand Down Expand Up @@ -817,7 +819,7 @@ def is_thenable(cls, obj):
)


_type_done_callbacks = {} # type: Dict[type, bool]
_type_done_callbacks = WeakKeyDictionary() # type: MutableMapping[type, bool]


def is_future_like(_type):
Expand Down
22 changes: 22 additions & 0 deletions tests/test_issues.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from concurrent.futures import ThreadPoolExecutor
from promise import Promise
import time
import weakref
import gc

executor = ThreadPoolExecutor(max_workers=40000)

Expand Down Expand Up @@ -108,3 +110,23 @@ def do(x):

p = Promise.resolve(None).then(do)
assert p.get() == "ok"


def test_issue_75():
def function_with_local_type():
class A:
pass

a = A()
assert a == Promise.resolve(a).get()

return weakref.ref(A)

weak_reference = function_with_local_type()

# The local type 'A' from the function is still kept alive by reference cycles.
gc.collect()

# Now the local type should have been garbage collected,
# such that the weak reference should be invalid.
assert not weak_reference()

0 comments on commit d99384f

Please sign in to comment.