Пример #1
0
def init_types():
    # This function initializes the module with some basic shareable
    # types. The function is deleted after it is called.
    # Shared versions of the container types list, tuple and dictionary
    # are implemented from scratch, and are treated specially.

    # Allow the names SharedList, SharedTuple and SharedDict to persist,
    # so that users may subtype them if desired.
    global SharedList, SharedTuple, SharedDict
    global NoSynchSharedList, nslist

    def seq_add(self, other):
        return self[:]+other

    def seq_radd(self, other):
        return other+self[:]

    def seq_mul(self, count):
        return self[:]*count

    def seq_contains(self, item):
        for x in self:
            if x == item:
                return 1
        return 0

    class SharedList(_core.SharedListBase):
        """List type whose instances live in shared memory."""
        __metaclass__ = SharedType
        __slots__ = []

        __add__ = seq_add
        __radd__ = seq_radd
        __mul__ = seq_mul
        __rmul__ = seq_mul
        __contains__ = seq_contains

        def __iadd__(self, other):
            self.extend(other)
            return self

        def __imul__(self, count):
            lr = range(len(self))
            for i in range(count-1):
                for j in lr:
                    self.append(self[j])
            return self

        def __getslice__(self, i, j):
            indices = range(len(self))[i:j]
            return [self[i] for i in indices]

        def count(self, item):
            result = 0
            for x in self:
                if x == item:
                    result += 1
            return result

        def extend(self, seq):
            if seq is not self:
                # Default implementation, uses iterator
                for item in seq:
                    self.append(item)
            else:
                # Extension by self, cannot use iterator
                for i in range(len(self)):
                    self.append(self[i])

        def index(self, item):
            for i in range(len(self)):
                if self[i] == item:
                    return i
            raise ValueError, "list.index(x): x not in list"

        def reverse(self):
            l = len(self) // 2
            for i in range(l):
                j = -i-1
                # A traditional swap does less work than
                # a, b = b, a -- although it is less elegant...
                tmp = self[i]
                self[i] = self[j]
                self[j] = tmp

    class SharedTuple(_core.SharedTupleBase):
        """Tuple type whose instances live in shared memory."""
        __metaclass__ = SharedType
        __slots__ = []

        __add__ = seq_add
        __radd__ = seq_radd
        __mul__ = seq_mul
        __rmul__ = seq_mul
        __contains__ = seq_contains

        def __getslice__(self, i, j):
            indices = range(len(self))[i:j]
            return tuple([self[i] for i in indices])

        def __str__(self):
            # Tuples cannot be recursive, so this is easy
            # to implement using Python code
            items = map(repr, self)
            return "("+", ".join(items)+")"

        __repr__ = __str__

    class SharedDict(_core.SharedDictBase):
        """Dictionary type whose instances live in shared memory."""
        __metaclass__ = SharedType
        __slots__ = []

    SharedListProxy = _proxy.MakeProxyType(SharedList)
    SharedTupleProxy = _proxy.MakeProxyType(SharedTuple)
    SharedDictProxy = _proxy.MakeProxyType(SharedDict)

    # This maps list to SharedList and so on - this is special, since
    # these shared types are not subtypes of their shareable equivalents,
    # as is normally the case.
    _core.register_type(list, SharedList, SharedListProxy, default_init)
    _core.register_type(tuple, SharedTuple, SharedTupleProxy, default_init)
    _core.register_type(dict, SharedDict, SharedDictProxy, default_init)

    # Produce basic immutable shared types
    for t in int, float, long, complex, str, unicode, Lock:
        allow_sharing(t, synch=None)

    class NoSynchSharedList(SharedList):
        __slots__ = []
        __synch__ = None

    class nslist(list):
        __slots__ = []

    _core.register_type(nslist, NoSynchSharedList,
                        _proxy.MakeProxyType(NoSynchSharedList), 
                        default_init)
Пример #2
0
def init_types():
    # This function initializes the module with some basic shareable
    # types. The function is deleted after it is called.
    # Shared versions of the container types list, tuple and dictionary
    # are implemented from scratch, and are treated specially.

    # Allow the names SharedList, SharedTuple and SharedDict to persist,
    # so that users may subtype them if desired.
    global SharedList, SharedTuple, SharedDict
    global NoSynchSharedList, nslist

    def seq_add(self, other):
        return self[:] + other

    def seq_radd(self, other):
        return other + self[:]

    def seq_mul(self, count):
        return self[:] * count

    def seq_contains(self, item):
        for x in self:
            if x == item:
                return 1
        return 0

    class SharedList(_core.SharedListBase):
        """List type whose instances live in shared memory."""
        __metaclass__ = SharedType
        __slots__ = []

        __add__ = seq_add
        __radd__ = seq_radd
        __mul__ = seq_mul
        __rmul__ = seq_mul
        __contains__ = seq_contains

        def __iadd__(self, other):
            self.extend(other)
            return self

        def __imul__(self, count):
            lr = range(len(self))
            for i in range(count - 1):
                for j in lr:
                    self.append(self[j])
            return self

        def __getslice__(self, i, j):
            indices = range(len(self))[i:j]
            return [self[i] for i in indices]

        def count(self, item):
            result = 0
            for x in self:
                if x == item:
                    result += 1
            return result

        def extend(self, seq):
            if seq is not self:
                # Default implementation, uses iterator
                for item in seq:
                    self.append(item)
            else:
                # Extension by self, cannot use iterator
                for i in range(len(self)):
                    self.append(self[i])

        def index(self, item):
            for i in range(len(self)):
                if self[i] == item:
                    return i
            raise ValueError, "list.index(x): x not in list"

        def reverse(self):
            l = len(self) // 2
            for i in range(l):
                j = -i - 1
                # A traditional swap does less work than
                # a, b = b, a -- although it is less elegant...
                tmp = self[i]
                self[i] = self[j]
                self[j] = tmp

    class SharedTuple(_core.SharedTupleBase):
        """Tuple type whose instances live in shared memory."""
        __metaclass__ = SharedType
        __slots__ = []

        __add__ = seq_add
        __radd__ = seq_radd
        __mul__ = seq_mul
        __rmul__ = seq_mul
        __contains__ = seq_contains

        def __getslice__(self, i, j):
            indices = range(len(self))[i:j]
            return tuple([self[i] for i in indices])

        def __str__(self):
            # Tuples cannot be recursive, so this is easy
            # to implement using Python code
            items = map(repr, self)
            return "(" + ", ".join(items) + ")"

        __repr__ = __str__

    class SharedDict(_core.SharedDictBase):
        """Dictionary type whose instances live in shared memory."""
        __metaclass__ = SharedType
        __slots__ = []

    SharedListProxy = _proxy.MakeProxyType(SharedList)
    SharedTupleProxy = _proxy.MakeProxyType(SharedTuple)
    SharedDictProxy = _proxy.MakeProxyType(SharedDict)

    # This maps list to SharedList and so on - this is special, since
    # these shared types are not subtypes of their shareable equivalents,
    # as is normally the case.
    _core.register_type(list, SharedList, SharedListProxy, default_init)
    _core.register_type(tuple, SharedTuple, SharedTupleProxy, default_init)
    _core.register_type(dict, SharedDict, SharedDictProxy, default_init)

    # Produce basic immutable shared types
    for t in int, float, long, complex, str, unicode, Lock:
        allow_sharing(t, synch=None)

    class NoSynchSharedList(SharedList):
        __slots__ = []
        __synch__ = None

    class nslist(list):
        __slots__ = []

    _core.register_type(nslist, NoSynchSharedList,
                        _proxy.MakeProxyType(NoSynchSharedList), default_init)
Пример #3
0
def allow_sharing(tp, init=None, synch=MONITOR):
    """allow_sharing(tp, synch=None) -> None

    Allows sharing of objects of the given type.  This must be called prior
    to any fork() calls.  The init parameter is an initialization function
    f(S, x) that should return a new instance of the type S, initialized from
    the object x.  The synch parameter may be None for immutable types,
    indicating that no synchronization is needed on these objects, or MONITOR
    for objects that desire monitor access semantics.

    Instances of shareable types should adhere to the following rules:
    * A nonempty __slots__ is not allowed.
    * No custom __getattribute__(), __setattr__() or  __delattr__() is allowed.
    * Extension types need not make room for a dictionary in their object
      structure, but they should have a nonzero tp_dictoffset if they want to
      support attributes.
    * No references to other objects should be stored in the object structure
      itself, but rather in the object's dictionary using the generic
      PyObject_SetAttribute() and friends.
    * Extension types should not override the tp_alloc and tp_free slots.
    * References to ``self'' should not be stored in a way that makes them
      persist beyond the lifetime of the call.
    """

    global _has_forked

    if isinstance(tp, ClassType):
        raise TypeError, "allow_sharing: old-style classes are not supported"

    if not isinstance(tp, type):
        raise TypeError, "allow_sharing: 1st argument (tp) must be a type"

    # Check if we've forked
    if _has_forked:
        raise ValueError("allow_sharing: this call must be made "
              "prior to any fork calls")

    # Check if the type is already registered
    if tp in _core.type_map:
        raise ValueError("allow_sharing: %s objects may already be shared." 
                                    % tp.__name__)

    # The given type may not override attribute access
    # except to provide a __getattr__ hook.
    if _core.overrides_attributes(tp):
        raise ValueError("allow_sharing: %s overrides __getattribute__, "
           "__setattr__ or __delattr__" % tp.__name__)

    # The given type may not have a nonempty __slots__
    tpdir = dir(tp)
    if "__slots__" in tpdir and len(tp.__slots__):
        raise ValueError("allow_sharing: %s has a nonempty __slots__"
                             % tp.__name__)

    # If the given type contains no __dict__ descriptor, then the type's
    # instances has no dictionary, so neither should those of the shared
    # type.
    if not "__dict__" in tpdir:
        d = {'__slots__': []}
    else:
        d = {}

    # Make up a name for the shared type
    name = "Shared"+tp.__name__.capitalize()

    # The shared type is produced by inheriting from the shareable type
    # using the SharedType meta-type
    stp = SharedType(name, (tp,), d)
    # Assign the __synch__ attribute of the new type
    if not hasattr(stp, "__synch__"):
        stp.__synch__ = synch

    # We also need a proxy type that looks like the shared type
    ptp = _proxy.MakeProxyType(stp)

    # Register the types + the initializer with the _core module and we're done
    _core.register_type(tp, stp, ptp, init or default_init)
Пример #4
0
def allow_sharing(tp, init=None, synch=MONITOR):
    """allow_sharing(tp, synch=None) -> None

    Allows sharing of objects of the given type.  This must be called prior
    to any fork() calls.  The init parameter is an initialization function
    f(S, x) that should return a new instance of the type S, initialized from
    the object x.  The synch parameter may be None for immutable types,
    indicating that no synchronization is needed on these objects, or MONITOR
    for objects that desire monitor access semantics.

    Instances of shareable types should adhere to the following rules:
    * A nonempty __slots__ is not allowed.
    * No custom __getattribute__(), __setattr__() or  __delattr__() is allowed.
    * Extension types need not make room for a dictionary in their object
      structure, but they should have a nonzero tp_dictoffset if they want to
      support attributes.
    * No references to other objects should be stored in the object structure
      itself, but rather in the object's dictionary using the generic
      PyObject_SetAttribute() and friends.
    * Extension types should not override the tp_alloc and tp_free slots.
    * References to ``self'' should not be stored in a way that makes them
      persist beyond the lifetime of the call.
    """

    global _has_forked

    if isinstance(tp, ClassType):
        raise TypeError, "allow_sharing: old-style classes are not supported"

    if not isinstance(tp, type):
        raise TypeError, "allow_sharing: 1st argument (tp) must be a type"

    # Check if we've forked
    if _has_forked:
        raise ValueError("allow_sharing: this call must be made "
                         "prior to any fork calls")

    # Check if the type is already registered
    if tp in _core.type_map:
        raise ValueError("allow_sharing: %s objects may already be shared." %
                         tp.__name__)

    # The given type may not override attribute access
    # except to provide a __getattr__ hook.
    if _core.overrides_attributes(tp):
        raise ValueError("allow_sharing: %s overrides __getattribute__, "
                         "__setattr__ or __delattr__" % tp.__name__)

    # The given type may not have a nonempty __slots__
    tpdir = dir(tp)
    if "__slots__" in tpdir and len(tp.__slots__):
        raise ValueError("allow_sharing: %s has a nonempty __slots__" %
                         tp.__name__)

    # If the given type contains no __dict__ descriptor, then the type's
    # instances has no dictionary, so neither should those of the shared
    # type.
    if not "__dict__" in tpdir:
        d = {'__slots__': []}
    else:
        d = {}

    # Make up a name for the shared type
    name = "Shared" + tp.__name__.capitalize()

    # The shared type is produced by inheriting from the shareable type
    # using the SharedType meta-type
    stp = SharedType(name, (tp, ), d)
    # Assign the __synch__ attribute of the new type
    if not hasattr(stp, "__synch__"):
        stp.__synch__ = synch

    # We also need a proxy type that looks like the shared type
    ptp = _proxy.MakeProxyType(stp)

    # Register the types + the initializer with the _core module and we're done
    _core.register_type(tp, stp, ptp, init or default_init)