# Path: pyactor/thread/channel.py
# class Channel(Queue):
#     """
#     Channel is the main communication mechanism between actors. It is
#     actually a simple facade to the queue.Queue python class.
#     """
# 
#     def __init__(self):
#         Queue.__init__(self)
# 
#     def send(self, msg):
#         """
#         It sends a message to the current channel.
# 
#         :param msg: The message sent to an actor. It is a dictionary using
#             the constants in util.py (:mod:`pyactor.util`).
#         """
#         self.put(msg)
# 
#     def receive(self, timeout=None):
#         """
#         It receives a message from the channel, blocking the calling
#         thread until the response is received, or the timeout is
#         triggered.
# 
#         :param int timeout: timeout to wait for messages. If none
#             provided it will block until a message arrives.
#         :return: returns a message sent to the channel. It is a dictionary
#             using the constants in util.py (:mod:`pyactor.util`).
#         """
#         return self.get(timeout=timeout)
# 
# Path: pyactor/exceptions.py
# class PyActorTimeoutError(Exception):
#     """Wait time expired."""
# 
#     def __init__(self, method='Not specified'):
#         self.method = method
# 
#     def __str__(self):
#         return f"Timeout triggered: {self.method!r}"
# 
# class FutureError(Exception):
#     """Some problem with the Future."""
# 
#     def __init__(self, value='Not specified'):
#         self.value = value
# 
#     def __str__(self):
#         return f"Future ERROR: {self.value!r}"
# 
# Path: pyactor/util.py
# TELL = 'TELL'
# 
# FUTURE = 'FUTURE'
# 
# TYPE = 'TYPE'
# 
# METHOD = 'METHOD'
# 
# PARAMS = 'PARAMS'
# 
# CHANNEL = 'CHANNEL'
# 
# TO = 'TO'
# 
# Path: pyactor/util.py
# def get_current():
#     if core_type == 'thread':
#         current = current_thread()
#     else:
#         current = getcurrent()
#     for host in hosts.values():
#         if current in host.threads.keys():
#             return host.actors[host.threads[current]]
#         elif current in host.pthreads.keys():
#             return host.actors[host.pthreads[current]]
# 
# def get_host():
#     if core_type == 'thread':
#         current = current_thread()
#     else:
#         current = getcurrent()
#     for host in hosts.values():
#         if current in host.threads.keys():
#             return host
#         elif current in host.pthreads.keys():
#             return host
#     return main_host
# 
# def get_lock():
#     if core_type == 'thread':
#         current = current_thread()
#     else:
#         return None
#     url = None
#     for host in hosts.values():
#         if current in host.threads.keys():
#             url = host.threads[current]
#         elif current in host.pthreads.keys():
#             url = host.pthreads[current]
#         if url in host.locks.keys():
#             lock = host.locks[url]
#             return lock
# 
# RPC_ID = 'RPC_ID'
# 
# RESULT = 'RESULT'


import uuid
from threading import Condition, Thread
from .channel import Channel
from ..exceptions import PyActorTimeoutError, FutureError
from ..util import TELL, FUTURE, TYPE, METHOD, PARAMS, CHANNEL, TO
from ..util import get_current, get_host, get_lock, RPC_ID, RESULT
        :raises: TimeoutError: If the timeout is reached before the
            future ends execution.
        """
        with self.__condition:
            if self.__state == FINISHED:
                return self.__exception

            lock = get_lock()
            if lock is not None:
                lock.release()
            self.__condition.wait(timeout)
            if lock is not None:
                lock.acquire()

            if self.__state == FINISHED:
                return self.__exception
            else:
                raise PyActorTimeoutError(f"Future: {self.__method!r}")

    def send_work(self):
        """
        Sends the query to the actor for it to start executing the work.

        It is possible to execute once again a future that has finished
        if necessary (overwriting the results), but only one execution
        at a time.
        """
        if self.__set_running():
            # msg = FutureRequest(FUTURE, self.__method, self.__params,
            #                     self.__channel, self.__target, self.__id)

# Path: pyactor/thread/channel.py
# class Channel(Queue):
#     """
#     Channel is the main communication mechanism between actors. It is
#     actually a simple facade to the queue.Queue python class.
#     """
# 
#     def __init__(self):
#         Queue.__init__(self)
# 
#     def send(self, msg):
#         """
#         It sends a message to the current channel.
# 
#         :param msg: The message sent to an actor. It is a dictionary using
#             the constants in util.py (:mod:`pyactor.util`).
#         """
#         self.put(msg)
# 
#     def receive(self, timeout=None):
#         """
#         It receives a message from the channel, blocking the calling
#         thread until the response is received, or the timeout is
#         triggered.
# 
#         :param int timeout: timeout to wait for messages. If none
#             provided it will block until a message arrives.
#         :return: returns a message sent to the channel. It is a dictionary
#             using the constants in util.py (:mod:`pyactor.util`).
#         """
#         return self.get(timeout=timeout)
# 
# Path: pyactor/exceptions.py
# class PyActorTimeoutError(Exception):
#     """Wait time expired."""
# 
#     def __init__(self, method='Not specified'):
#         self.method = method
# 
#     def __str__(self):
#         return f"Timeout triggered: {self.method!r}"
# 
# class FutureError(Exception):
#     """Some problem with the Future."""
# 
#     def __init__(self, value='Not specified'):
#         self.value = value
# 
#     def __str__(self):
#         return f"Future ERROR: {self.value!r}"
# 
# Path: pyactor/util.py
# TELL = 'TELL'
# 
# FUTURE = 'FUTURE'
# 
# TYPE = 'TYPE'
# 
# METHOD = 'METHOD'
# 
# PARAMS = 'PARAMS'
# 
# CHANNEL = 'CHANNEL'
# 
# TO = 'TO'
# 
# Path: pyactor/util.py
# def get_current():
#     if core_type == 'thread':
#         current = current_thread()
#     else:
#         current = getcurrent()
#     for host in hosts.values():
#         if current in host.threads.keys():
#             return host.actors[host.threads[current]]
#         elif current in host.pthreads.keys():
#             return host.actors[host.pthreads[current]]
# 
# def get_host():
#     if core_type == 'thread':
#         current = current_thread()
#     else:
#         current = getcurrent()
#     for host in hosts.values():
#         if current in host.threads.keys():
#             return host
#         elif current in host.pthreads.keys():
#             return host
#     return main_host
# 
# def get_lock():
#     if core_type == 'thread':
#         current = current_thread()
#     else:
#         return None
#     url = None
#     for host in hosts.values():
#         if current in host.threads.keys():
#             url = host.threads[current]
#         elif current in host.pthreads.keys():
#             url = host.pthreads[current]
#         if url in host.locks.keys():
#             lock = host.locks[url]
#             return lock
# 
# RPC_ID = 'RPC_ID'
# 
# RESULT = 'RESULT'


# Path: pyactor/thread/future.py
import uuid
from threading import Condition, Thread
from .channel import Channel
from ..exceptions import PyActorTimeoutError, FutureError
from ..util import TELL, FUTURE, TYPE, METHOD, PARAMS, CHANNEL, TO
from ..util import get_current, get_host, get_lock, RPC_ID, RESULT

        :raises: TimeoutError: If the timeout is reached before the
            future ends execution.
        """
        with self.__condition:
            if self.__state == FINISHED:
                return self.__exception

            lock = get_lock()
            if lock is not None:
                lock.release()
            self.__condition.wait(timeout)
            if lock is not None:
                lock.acquire()

            if self.__state == FINISHED:
                return self.__exception
            else:
                raise PyActorTimeoutError(f"Future: {self.__method!r}")

    def send_work(self):
        """
        Sends the query to the actor for it to start executing the work.

        It is possible to execute once again a future that has finished
        if necessary (overwriting the results), but only one execution
        at a time.
        """
        if self.__set_running():
            # msg = FutureRequest(FUTURE, self.__method, self.__params,
            #                     self.__channel, self.__target, self.__id)

            msg = {TYPE: FUTURE, METHOD: self.__method, PARAMS: self.__params,