Commit 1a6fdfdd authored by Jason Madden's avatar Jason Madden

Unify the implementation of Group/Pool imap/map/apply and ThreadPool imap/map/apply.

This ensures ThreadPool has the same API, including accepting multiple iterables in imap.

Also, capture the _raise_exception method of a failed greenlet and use it to raise the original traceback from those methods.
parent 31cc411d
...@@ -4,6 +4,15 @@ ...@@ -4,6 +4,15 @@
.. currentmodule:: gevent .. currentmodule:: gevent
Unreleased
==========
- ``gevent.threadpool.ThreadPool.imap`` and ``imap_unordered`` now
accept multiple iterables.
- (Experimental) Exceptions raised from iterating using the
``ThreadPool`` or ``Group`` mapping/application functions should now
have the original traceback.
1.1a1 (Jun 29, 2015) 1.1a1 (Jun 29, 2015)
==================== ====================
......
This diff is collapsed.
...@@ -5,7 +5,7 @@ import os ...@@ -5,7 +5,7 @@ import os
from gevent.hub import get_hub, getcurrent, sleep, integer_types from gevent.hub import get_hub, getcurrent, sleep, integer_types
from gevent.event import AsyncResult from gevent.event import AsyncResult
from gevent.greenlet import Greenlet from gevent.greenlet import Greenlet
from gevent.pool import IMap, IMapUnordered from gevent.pool import GroupMappingMixin
from gevent.lock import Semaphore from gevent.lock import Semaphore
from gevent._threading import Lock, Queue, start_new_thread from gevent._threading import Lock, Queue, start_new_thread
...@@ -17,7 +17,7 @@ __all__ = ['ThreadPool', ...@@ -17,7 +17,7 @@ __all__ = ['ThreadPool',
'ThreadResult'] 'ThreadResult']
class ThreadPool(object): class ThreadPool(GroupMappingMixin):
def __init__(self, maxsize, hub=None): def __init__(self, maxsize, hub=None):
if hub is None: if hub is None:
...@@ -224,57 +224,16 @@ class ThreadPool(object): ...@@ -224,57 +224,16 @@ class ThreadPool(object):
return result return result
raise result raise result
def apply(self, func, args=None, kwds=None): def _apply_immediately(self):
"""Equivalent of the apply() builtin function. It blocks till the result is ready.""" # we always pass apply() off to the threadpool
if args is None: return False
args = ()
if kwds is None:
kwds = {}
return self.spawn(func, *args, **kwds).get()
def apply_cb(self, func, args=None, kwds=None, callback=None): def _apply_async_cb_spawn(self, callback, result):
result = self.apply(func, args, kwds)
if callback is not None:
callback(result) callback(result)
return result
def apply_async(self, func, args=None, kwds=None, callback=None):
"""A variant of the apply() method which returns a Greenlet object.
If callback is specified then it should be a callable which accepts a single argument. When the result becomes ready
callback is applied to it (unless the call failed)."""
if args is None:
args = ()
if kwds is None:
kwds = {}
return Greenlet.spawn(self.apply_cb, func, args, kwds, callback)
def map(self, func, iterable):
return list(self.imap(func, iterable))
def map_cb(self, func, iterable, callback=None): def _apply_async_use_greenlet(self):
result = self.map(func, iterable) # Always go to Greenlet because our self.spawn uses threads
if callback is not None: return True
callback(result)
return result
def map_async(self, func, iterable, callback=None):
"""
A variant of the map() method which returns a Greenlet object.
If callback is specified then it should be a callable which accepts a
single argument.
"""
return Greenlet.spawn(self.map_cb, func, iterable, callback)
def imap(self, func, iterable):
"""An equivalent of itertools.imap()"""
return IMap.spawn(func, iterable, spawn=self.spawn)
def imap_unordered(self, func, iterable):
"""The same as imap() except that the ordering of the results from the
returned iterator should be considered in arbitrary order."""
return IMapUnordered.spawn(func, iterable, spawn=self.spawn)
class ThreadResult(object): class ThreadResult(object):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment