import threading

from rx.internal import noop

class Disposable(object):
    """Main disposable class"""
    def __init__(self, action=None):
        """Creates a disposable object that invokes the specified action when
        disposed.

        Keyword arguments:
        dispose -- Action to run during the first call to Disposable.dispose.
            The action is guaranteed to be run at most once.

        Returns the disposable object that runs the given action upon disposal.
        """
        self.is_disposed = False
        self.action = action

        self.lock = threading.Lock()

    def dispose(self):
        """Performs the task of cleaning up resources."""

        dispose = False
        with self.lock:
            if not self.is_disposed:
                dispose = True
                self.is_disposed = True
                
        if dispose and self.action:
            self.action()

    @classmethod
    def empty(cls):
        return cls(noop)

    @classmethod
    def create(cls, action):
        return cls(action)

import threading

from rx.internal import noop

class Disposable(object):
    """Main disposable class"""
    def __init__(self, action=None):
        """Creates a disposable object that invokes the specified action when
        disposed.

        Keyword arguments:
        dispose -- Action to run during the first call to Disposable.dispose.
            The action is guaranteed to be run at most once.

        Returns the disposable object that runs the given action upon disposal.
        """
        self.is_disposed = False
        self.action = action

        self.lock = threading.Lock()

    def dispose(self):
        """Performs the task of cleaning up resources."""

        dispose = False
        with self.lock:
            if not self.is_disposed:
                dispose = True
                self.is_disposed = True
                
        if dispose and self.action:
            self.action()

    def __enter__(self):
        """Context management protocol"""
        
        pass
    
    def __exit__(self, type, value, traceback):
        """Context management protocol"""
        
        self.dispose()

    @classmethod
    def empty(cls):
        return cls(noop)

    @classmethod
    def create(cls, action):
        return cls(action)

Make disposables support context management protocol