# Path: turbo/flux.py
# class Mutation(CallFuncAsAttr):
# 
#     @property
#     def _name(self):
#         return 'mutation_%s' % id(self)
# 
# def register(state):
#     def outwrapper(func):
#         state.register(func)
# 
#         @functools.wraps(func)
#         def wrapper(*args, **kwargs):
#             return func(*args, **kwargs)
# 
#         return wrapper
#     return outwrapper
# 
# class State(object):
# 
#     __slots__ = ['_state']
# 
#     def __init__(self, file_attr):
#         name = file_attr
#         filepath = os.path.abspath(file_attr)
#         if os.path.isfile(filepath):
#             name, ext = os.path.splitext(os.path.basename(filepath))
# 
#         if name in state:
#             raise KeyError('state %s has already existed' % name)
# 
#         self._state = ObjectDict()
#         state[name] = self._state
# 
#     def __setattr__(self, name, value):
#         if name in self.__slots__:
#             return super(State, self).__setattr__(name, value)
# 
#         self._state[name] = value
# 
#     def __getattr__(self, name):
#         if name not in self._state:
#             raise AttributeError("%s object has no attribute '%s'" %
#                                  (self.__class__.__name__, name))
# 
#         return self._state[name]


import logging
from tornado.concurrent import Future
from turbo.flux import Mutation, register, State
class MessageBuffer(object):

    def __init__(self):
        self.waiters = set()
        self.cache = []
        self.cache_size = 200

    def wait_for_messages(self, cursor=None):
        # Construct a Future to return to our caller.  This allows
        # wait_for_messages to be yielded from a coroutine even though
        # it is not a coroutine itself.  We will set the result of the
        # Future when results are available.
        result_future = Future()
        if cursor:
            new_count = 0
            for msg in reversed(self.cache):
                if msg["id"] == cursor:
                    break
                new_count += 1
            if new_count:
                result_future.set_result(self.cache[-new_count:])
                return result_future
        self.waiters.add(result_future)
        return result_future

    def cancel_wait(self, future):
        self.waiters.remove(future)
        # Set an empty result to unblock any coroutines waiting.
        future.set_result([])


# Path: turbo/flux.py
# class Mutation(CallFuncAsAttr):
# 
#     @property
#     def _name(self):
#         return 'mutation_%s' % id(self)
# 
# def register(state):
#     def outwrapper(func):
#         state.register(func)
# 
#         @functools.wraps(func)
#         def wrapper(*args, **kwargs):
#             return func(*args, **kwargs)
# 
#         return wrapper
#     return outwrapper
# 
# class State(object):
# 
#     __slots__ = ['_state']
# 
#     def __init__(self, file_attr):
#         name = file_attr
#         filepath = os.path.abspath(file_attr)
#         if os.path.isfile(filepath):
#             name, ext = os.path.splitext(os.path.basename(filepath))
# 
#         if name in state:
#             raise KeyError('state %s has already existed' % name)
# 
#         self._state = ObjectDict()
#         state[name] = self._state
# 
#     def __setattr__(self, name, value):
#         if name in self.__slots__:
#             return super(State, self).__setattr__(name, value)
# 
#         self._state[name] = value
# 
#     def __getattr__(self, name):
#         if name not in self._state:
#             raise AttributeError("%s object has no attribute '%s'" %
#                                  (self.__class__.__name__, name))
# 
#         return self._state[name]


# Path: demos/store/modules/chat.py
import logging
from tornado.concurrent import Future
from turbo.flux import Mutation, register, State

class MessageBuffer(object):

    def __init__(self):
        self.waiters = set()
        self.cache = []
        self.cache_size = 200

    def wait_for_messages(self, cursor=None):
        # Construct a Future to return to our caller.  This allows
        # wait_for_messages to be yielded from a coroutine even though
        # it is not a coroutine itself.  We will set the result of the
        # Future when results are available.
        result_future = Future()
        if cursor:
            new_count = 0
            for msg in reversed(self.cache):
                if msg["id"] == cursor:
                    break
                new_count += 1
            if new_count:
                result_future.set_result(self.cache[-new_count:])
                return result_future
        self.waiters.add(result_future)
        return result_future

    def cancel_wait(self, future):
        self.waiters.remove(future)
        # Set an empty result to unblock any coroutines waiting.
        future.set_result([])


    def new_messages(self, messages):