# Path: evergreen/core/utils.py
# class Result(object):
#     """
#     Result is an internal object which is meant to be used like a Future, but being more
#     lightweight and supporting a single waiter. Example:
# 
#     result = Result()
# 
#     def f1():
#         with result:
#             some_async_func()
#             return result.get()
# 
#     def some_async_func():
#         # this function runs in a different task
#         ...
#         result.set_value(42)
#     """
# 
#     __slots__ = ['_lock', '_cond', '_locked', '_used', '_exc', '_value']
# 
#     def __init__(self):
#         self._lock = Lock()
#         self._cond = Condition(Lock())
#         self._locked = False
#         self._used = False
#         self._exc = self._value = Null
# 
#     def acquire(self):
#         self._lock.acquire()
#         self._locked = True
# 
#     def release(self):
#         self._lock.release()
#         self._locked = False
#         self._used = False
#         self._exc = self._value = Null
# 
#     def get(self):
#         assert self._locked
#         assert not self._used
#         try:
#             with self._cond:
#                 if self._exc == self._value == Null:
#                     self._cond.wait()
#             if self._exc != Null:
#                 raise self._exc
#             assert self._value != Null
#             return self._value
#         finally:
#             self._used = True
#             self._exc = self._value = Null
# 
#     def set_value(self, value):
#         assert self._locked
#         assert not self._used
#         assert self._exc == self._value == Null
#         with self._cond:
#             self._value = value
#             self._cond.notify_all()
# 
#     def set_exception(self, value):
#         assert self._locked
#         assert not self._used
#         assert self._exc == self._value == Null
#         with self._cond:
#             self._exc = value
#             self._cond.notify_all()
# 
#     def __enter__(self):
#         self.acquire()
# 
#     def __exit__(self, typ, val, tb):
#         self.release()
# 
# Path: evergreen/event.py
# class Event(object):
# 
#     def __init__(self):
#         self._cond = Condition(Lock())
#         self._flag = False
# 
#     def is_set(self):
#         return self._flag
# 
#     def set(self):
#         self._cond.acquire()
#         try:
#             self._flag = True
#             self._cond.notify_all()
#         finally:
#             self._cond.release()
# 
#     def clear(self):
#         self._cond.acquire()
#         try:
#             self._flag = False
#         finally:
#             self._cond.release()
# 
#     def wait(self, timeout=None):
#         self._cond.acquire()
#         try:
#             signaled = self._flag
#             if not signaled:
#                 signaled = self._cond.wait(timeout)
#             return signaled
#         finally:
#             self._cond.release()
# 
# Path: evergreen/io/errno.py
# def _bootstrap():
# 
# Path: evergreen/log.py



import pyuv
import evergreen
from evergreen.core.utils import Result
from evergreen.event import Event
from evergreen.io import errno
from evergreen.log import log
        self._handle.send(addr, data, self.__send_cb)
        if self._pending_writes == 0:
            self._flush_event.clear()
        self._pending_writes += 1

    def receive(self):
        self._check_closed()
        with self._receive_result:
            self._handle.start_recv(self.__receive_cb)
            return self._receive_result.get()

    def flush(self):
        self._check_closed()
        self._flush_event.wait()

    def close(self):
        if self._closed:
            return
        self._closed = True
        self._handle.close()

    def _check_closed(self):
        if self._closed:
            raise UDPError('endpoint is closed')

    def __send_cb(self, handle, error):
        self._pending_writes -= 1
        if self._pending_writes == 0:
            self._flush_event.set()
        if error is not None:

# Path: evergreen/core/utils.py
# class Result(object):
#     """
#     Result is an internal object which is meant to be used like a Future, but being more
#     lightweight and supporting a single waiter. Example:
# 
#     result = Result()
# 
#     def f1():
#         with result:
#             some_async_func()
#             return result.get()
# 
#     def some_async_func():
#         # this function runs in a different task
#         ...
#         result.set_value(42)
#     """
# 
#     __slots__ = ['_lock', '_cond', '_locked', '_used', '_exc', '_value']
# 
#     def __init__(self):
#         self._lock = Lock()
#         self._cond = Condition(Lock())
#         self._locked = False
#         self._used = False
#         self._exc = self._value = Null
# 
#     def acquire(self):
#         self._lock.acquire()
#         self._locked = True
# 
#     def release(self):
#         self._lock.release()
#         self._locked = False
#         self._used = False
#         self._exc = self._value = Null
# 
#     def get(self):
#         assert self._locked
#         assert not self._used
#         try:
#             with self._cond:
#                 if self._exc == self._value == Null:
#                     self._cond.wait()
#             if self._exc != Null:
#                 raise self._exc
#             assert self._value != Null
#             return self._value
#         finally:
#             self._used = True
#             self._exc = self._value = Null
# 
#     def set_value(self, value):
#         assert self._locked
#         assert not self._used
#         assert self._exc == self._value == Null
#         with self._cond:
#             self._value = value
#             self._cond.notify_all()
# 
#     def set_exception(self, value):
#         assert self._locked
#         assert not self._used
#         assert self._exc == self._value == Null
#         with self._cond:
#             self._exc = value
#             self._cond.notify_all()
# 
#     def __enter__(self):
#         self.acquire()
# 
#     def __exit__(self, typ, val, tb):
#         self.release()
# 
# Path: evergreen/event.py
# class Event(object):
# 
#     def __init__(self):
#         self._cond = Condition(Lock())
#         self._flag = False
# 
#     def is_set(self):
#         return self._flag
# 
#     def set(self):
#         self._cond.acquire()
#         try:
#             self._flag = True
#             self._cond.notify_all()
#         finally:
#             self._cond.release()
# 
#     def clear(self):
#         self._cond.acquire()
#         try:
#             self._flag = False
#         finally:
#             self._cond.release()
# 
#     def wait(self, timeout=None):
#         self._cond.acquire()
#         try:
#             signaled = self._flag
#             if not signaled:
#                 signaled = self._cond.wait(timeout)
#             return signaled
#         finally:
#             self._cond.release()
# 
# Path: evergreen/io/errno.py
# def _bootstrap():
# 
# Path: evergreen/log.py



# Path: evergreen/io/udp.py
import pyuv
import evergreen
from evergreen.core.utils import Result
from evergreen.event import Event
from evergreen.io import errno
from evergreen.log import log

        self._handle.send(addr, data, self.__send_cb)
        if self._pending_writes == 0:
            self._flush_event.clear()
        self._pending_writes += 1

    def receive(self):
        self._check_closed()
        with self._receive_result:
            self._handle.start_recv(self.__receive_cb)
            return self._receive_result.get()

    def flush(self):
        self._check_closed()
        self._flush_event.wait()

    def close(self):
        if self._closed:
            return
        self._closed = True
        self._handle.close()

    def _check_closed(self):
        if self._closed:
            raise UDPError('endpoint is closed')

    def __send_cb(self, handle, error):
        self._pending_writes -= 1
        if self._pending_writes == 0:
            self._flush_event.set()
        if error is not None:

            log.debug('send failed: %d %s', error, pyuv.errno.strerror(error))