# Path: pyactor/green_thread/channel.py
# class Channel(Queue):
#     """
#     Channel is the main communication mechanism between actors. It is
#     actually a simple facade to the gevent.Queue 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 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
# 
# RPC_ID = 'RPC_ID'
# 
# RESULT = 'RESULT'


import uuid
from gevent import spawn
from gevent.event import Event
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, RPC_ID, RESULT

    def __get__result(self):
        if self.__exception is not None:
            raise self.__exception
        else:
            return self.__result

    def add_callback(self, method):
        """
        Attaches a method that will be called when the future finishes.

        :param method: A callable from an actor that will be called
            when the future completes. The only argument for that
            method must be the future itself from which you can get the
            result though `future.:meth:`result()``. If the future has
            already completed, then the callable will be called
            immediately.

        .. note:: This functionality only works when called from an actor,
            specifying a method from the same actor.
        """
        from_actor = get_current()
        if from_actor is not None:
            callback = (method, from_actor.channel, from_actor.url)
            # with self.__condition:
            if self.__state is not FINISHED:
                self.__callbacks.append(callback)
                return
            # Invoke the callback directly
            # msg = TellRequest(TELL, method, [self], from_actor.url)

# Path: pyactor/green_thread/channel.py
# class Channel(Queue):
#     """
#     Channel is the main communication mechanism between actors. It is
#     actually a simple facade to the gevent.Queue 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 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
# 
# RPC_ID = 'RPC_ID'
# 
# RESULT = 'RESULT'


# Path: pyactor/green_thread/future.py
import uuid
from gevent import spawn
from gevent.event import Event
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, RPC_ID, RESULT


    def __get__result(self):
        if self.__exception is not None:
            raise self.__exception
        else:
            return self.__result

    def add_callback(self, method):
        """
        Attaches a method that will be called when the future finishes.

        :param method: A callable from an actor that will be called
            when the future completes. The only argument for that
            method must be the future itself from which you can get the
            result though `future.:meth:`result()``. If the future has
            already completed, then the callable will be called
            immediately.

        .. note:: This functionality only works when called from an actor,
            specifying a method from the same actor.
        """
        from_actor = get_current()
        if from_actor is not None:
            callback = (method, from_actor.channel, from_actor.url)
            # with self.__condition:
            if self.__state is not FINISHED:
                self.__callbacks.append(callback)
                return
            # Invoke the callback directly
            # msg = TellRequest(TELL, method, [self], from_actor.url)

            msg = {TYPE: TELL, METHOD: method, PARAMS: ([self], {}),