QuantumGhost
8/15/2017 - 4:10 AM

symbol.py

class Symbol:
    __registry = {}
    __lock = Lock()
    __slots__ = ('name',)

    def __new__(cls, name):
        instance = cls.__registry.get(name)
        if not instance:
            with cls.__lock:
                # A classical double-checked lock pattern.
                # the second check is necessary
                # considering the following procedure:
                # t1 calls new
                # t2 calls new
                # t1 check registry, found symbol not exist
                # t2 check registry, found symbol not exist
                # t1 acquires lock, creating symbol
                # t2 waits for lock
                # t1 create symbol and store it in registry
                # t2 acquire lock, create symbol and store it in registry
                # now two symbols with same name are created, we're in trouble.
                instance = cls.__registry.get(name)
                if instance:
                    return instance
                instance = super().__new__(cls)
                instance.name = name
                cls.__registry[name] = instance
        return instance

    def __init__(self, name):
        self.name = name

    def __eq__(self, other):
        return id(self) == id(other)

    def __hash__(self):
        return hash(self.name)

    def __str__(self):
        return "Symbol({})".format(self.name)

    def __repr__(self):
        return 'Symbol("{}")'.format(self.name)

    def __getnewargs__(self):
        return self.name,


STOP = Symbol('stop')