from __future__ import with_statement
import threado
import threading
import Queue

class ThreadPool(object):
    def __init__(self, idle_time=5.0):
        self.lock = threading.Lock()
        self.threads = list()
        self.idle_time = idle_time

    @threado.stream
    def run(inner, self, func, *args, **keys):
        with self.lock:
            if self.threads:
                thread, queue = self.threads.pop()
            else:
                queue = Queue.Queue()
                thread = threading.Thread(target=self._thread, args=(queue,))
                thread.setDaemon(True)

        channel = threado.Channel()    
        queue.put((channel, func, args, keys))
        if not thread.isAlive():
            thread.start()

        result = yield channel
        inner.finish(result)

    def _thread(self, queue):
        item = threading.currentThread(), queue

        while True:
            try:
                task = queue.get(True, self.idle_time)
            except Queue.Empty:
                with self.lock:
                    if item not in self.threads:
                        continue
                    self.threads.remove(item)
                    return
            if task is None:
                return

            channel, func, args, keys = task
            try:
                result = func(*args, **keys)
            except:
                self.threads.append(item)
                channel.rethrow()
            else:
                self.threads.append(item)
                channel.finish(result)
thread_pool = ThreadPool()

run = thread_pool.run

from __future__ import with_statement
import sys
import threado
import threading
import Queue

class ThreadPool(object):
    def __init__(self, idle_time=5.0):
        self.lock = threading.Lock()
        self.threads = list()
        self.idle_time = idle_time

    def run(self, func, *args, **keys):
        with self.lock:
            if self.threads:
                thread, queue = self.threads.pop()
            else:
                queue = Queue.Queue()
                thread = threading.Thread(target=self._thread, args=(queue,))
                thread.setDaemon(True)

        channel = threado.Channel()    
        queue.put((channel, func, args, keys))
        if not thread.isAlive():
            thread.start()

        return channel

    def _thread(self, queue):
        item = threading.currentThread(), queue

        while True:
            try:
                task = queue.get(True, self.idle_time)
            except Queue.Empty:
                with self.lock:
                    if item not in self.threads:
                        continue
                    self.threads.remove(item)
                    return
            if task is None:
                return

            channel, func, args, keys = task
            try:
                result = func(*args, **keys)
            except:
                self.threads.append(item)
                channel.rethrow()
            else:
                self.threads.append(item)
                channel.finish(result)
thread_pool = ThreadPool()

run = thread_pool.run

Fix a weird situation when a function run in a thread raises StopIteration, which was erroneusly interpreted that the thread returned None.
Fix a weird situation when a function run in a thread raises StopIteration, which was erroneusly interpreted that the thread returned None.

  from __future__ import with_statement
+ import sys
  import threado
  import threading
  import Queue
  
  class ThreadPool(object):
      def __init__(self, idle_time=5.0):
          self.lock = threading.Lock()
          self.threads = list()
          self.idle_time = idle_time
  
-     @threado.stream
-     def run(inner, self, func, *args, **keys):
+     def run(self, func, *args, **keys):
          with self.lock:
              if self.threads:
                  thread, queue = self.threads.pop()
              else:
                  queue = Queue.Queue()
                  thread = threading.Thread(target=self._thread, args=(queue,))
                  thread.setDaemon(True)
  
          channel = threado.Channel()    
          queue.put((channel, func, args, keys))
          if not thread.isAlive():
              thread.start()
  
+         return channel
-         result = yield channel
-         inner.finish(result)
  
      def _thread(self, queue):
          item = threading.currentThread(), queue
  
          while True:
              try:
                  task = queue.get(True, self.idle_time)
              except Queue.Empty:
                  with self.lock:
                      if item not in self.threads:
                          continue
                      self.threads.remove(item)
                      return
              if task is None:
                  return
  
              channel, func, args, keys = task
              try:
                  result = func(*args, **keys)
              except:
                  self.threads.append(item)
                  channel.rethrow()
              else:
                  self.threads.append(item)
                  channel.finish(result)
  thread_pool = ThreadPool()
  
  run = thread_pool.run
  
Fix a weird situation when a function run in a thread raises StopIteration, which was erroneusly interpreted that the thread returned None.
## Code Before:
from __future__ import with_statement
import threado
import threading
import Queue

class ThreadPool(object):
    def __init__(self, idle_time=5.0):
        self.lock = threading.Lock()
        self.threads = list()
        self.idle_time = idle_time

    @threado.stream
    def run(inner, self, func, *args, **keys):
        with self.lock:
            if self.threads:
                thread, queue = self.threads.pop()
            else:
                queue = Queue.Queue()
                thread = threading.Thread(target=self._thread, args=(queue,))
                thread.setDaemon(True)

        channel = threado.Channel()    
        queue.put((channel, func, args, keys))
        if not thread.isAlive():
            thread.start()

        result = yield channel
        inner.finish(result)

    def _thread(self, queue):
        item = threading.currentThread(), queue

        while True:
            try:
                task = queue.get(True, self.idle_time)
            except Queue.Empty:
                with self.lock:
                    if item not in self.threads:
                        continue
                    self.threads.remove(item)
                    return
            if task is None:
                return

            channel, func, args, keys = task
            try:
                result = func(*args, **keys)
            except:
                self.threads.append(item)
                channel.rethrow()
            else:
                self.threads.append(item)
                channel.finish(result)
thread_pool = ThreadPool()

run = thread_pool.run

## Instruction:
Fix a weird situation when a function run in a thread raises StopIteration, which was erroneusly interpreted that the thread returned None.
## Code After:
from __future__ import with_statement
import sys
import threado
import threading
import Queue

class ThreadPool(object):
    def __init__(self, idle_time=5.0):
        self.lock = threading.Lock()
        self.threads = list()
        self.idle_time = idle_time

    def run(self, func, *args, **keys):
        with self.lock:
            if self.threads:
                thread, queue = self.threads.pop()
            else:
                queue = Queue.Queue()
                thread = threading.Thread(target=self._thread, args=(queue,))
                thread.setDaemon(True)

        channel = threado.Channel()    
        queue.put((channel, func, args, keys))
        if not thread.isAlive():
            thread.start()

        return channel

    def _thread(self, queue):
        item = threading.currentThread(), queue

        while True:
            try:
                task = queue.get(True, self.idle_time)
            except Queue.Empty:
                with self.lock:
                    if item not in self.threads:
                        continue
                    self.threads.remove(item)
                    return
            if task is None:
                return

            channel, func, args, keys = task
            try:
                result = func(*args, **keys)
            except:
                self.threads.append(item)
                channel.rethrow()
            else:
                self.threads.append(item)
                channel.finish(result)
thread_pool = ThreadPool()

run = thread_pool.run
