#encoding = utf8
import threading


class EventBus:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, *args, **kwargs):
        if not cls._instance:
            with cls._lock:
                if not cls._instance:
                    cls._instance = super(EventBus, cls).__new__(cls, *args, **kwargs)
        return cls._instance

    def __init__(self):
        if not hasattr(self, '_initialized'):
            self._listeners = {}
            self._lock = threading.Lock()
            self._initialized = True

    def register(self, event_type, listener):
        with self._lock:
            if event_type not in self._listeners:
                self._listeners[event_type] = []
            self._listeners[event_type].append(listener)

    def unregister(self, event_type, listener):
        with self._lock:
            if event_type in self._listeners:
                self._listeners[event_type].remove(listener)
                if not self._listeners[event_type]:
                    del self._listeners[event_type]

    def post(self, event_type, *args, **kwargs):
        with self._lock:
            listeners = self._listeners.get(event_type, []).copy()
        for listener in listeners:
            listener(*args, **kwargs)
