<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def thread_pool(*workers, results=None, end_of_queue=EndOfQueue):
 """Returns a |pull| object, call it ``r``, starting a thread for each given worker. Each thread pulls from the source that ``r`` is connected to, and the returned results are pushed to a |Queue|. ``r`` yields from the other end of the same |Queue|. The target function for each thread is |patch|, which can be stopped by exhausting the source. If all threads have ended, the result queue receives end-of-queue. :param results: If results should go somewhere else than a newly constructed |Queue|, a different |Connection| object can be given. :type results: |Connection| :param end_of_queue: end-of-queue signal object passed on to the creation of the |Queue| object. :rtype: |pull| """

    if results is None:
        results = Queue(end_of_queue=end_of_queue)

    count = thread_counter(results.close)

    @pull
    def thread_pool_results(source):
        for worker in workers:
            t = threading.Thread(
                target=count(patch),
                args=(pull(source) >> worker, results.sink),
                daemon=True)
            t.start()

        yield from results.source()

    return thread_pool_results