Thomas Heller <[EMAIL PROTECTED]> added the comment:

roudkerk schrieb:
> roudkerk <[EMAIL PROTECTED]> added the comment:
> 
> This patch to sharedctypes should fix the problem by adding a
> __reduce_ex__() method to a shared ctype object instead of using copy_reg.

I can confirm that the patch fixes the problem on Windows (running test_ctypes
before test_multiprocessing).

However, the patch did not apply cleanly to current SVN trunk - I had to 
manually
patch the code.  I'll attach the patch that I have now when I run 'svn diff' as
multiprocessing.patch (hope it works, sending as email attachment).

Added file: http://bugs.python.org/file10654/multiprocessing.patch

_______________________________________
Python tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue3125>
_______________________________________
Index: Lib/multiprocessing/sharedctypes.py
===================================================================
--- Lib/multiprocessing/sharedctypes.py (revision 64378)
+++ Lib/multiprocessing/sharedctypes.py (working copy)
@@ -9,7 +9,6 @@
 import sys
 import ctypes
 import weakref
-import copy_reg
 
 from multiprocessing import heap, RLock
 from multiprocessing.forking import assert_spawning
@@ -33,17 +32,13 @@
 #
 #
 
-def _new_value(type_):
-    size = ctypes.sizeof(type_)
-    wrapper = heap.BufferWrapper(size)
-    return rebuild_ctype(type_, wrapper, None)
-
 def RawValue(typecode_or_type, *args):
     '''
     Returns a ctypes object allocated from shared memory
     '''
     type_ = typecode_to_type.get(typecode_or_type, typecode_or_type)
-    obj = _new_value(type_)
+    type_size = ctypes.sizeof(type_)
+    obj = build_ctype(type_, heap.BufferWrapper(type_size), None)
     ctypes.memset(ctypes.addressof(obj), 0, ctypes.sizeof(obj))
     obj.__init__(*args)
     return obj
@@ -53,14 +48,16 @@
     Returns a ctypes array allocated from shared memory
     '''
     type_ = typecode_to_type.get(typecode_or_type, typecode_or_type)
+    type_size = ctypes.sizeof(type_)
     if isinstance(size_or_initializer, int):
-        type_ = type_ * size_or_initializer
-        return _new_value(type_)
+        size = size_or_initializer
+        obj = build_ctype(type_, heap.BufferWrapper(type_size*size), size)
+        ctypes.memset(ctypes.addressof(obj), 0, ctypes.sizeof(obj))
     else:
-        type_ = type_ * len(size_or_initializer)
-        result = _new_value(type_)
-        result.__init__(*size_or_initializer)
-        return result
+        size = len(size_or_initializer)
+        obj = build_ctype(type_, heap.BufferWrapper(type_size*size), size)
+        obj.__init__(*size_or_initializer)
+    return obj
 
 def Value(typecode_or_type, *args, **kwds):
     '''
@@ -117,20 +114,18 @@
 # Functions for pickling/unpickling
 #
 
-def reduce_ctype(obj):
-    assert_spawning(obj)
-    if isinstance(obj, ctypes.Array):
-        return rebuild_ctype, (obj._type_, obj._wrapper, obj._length_)
-    else:
-        return rebuild_ctype, (type(obj), obj._wrapper, None)
-
-def rebuild_ctype(type_, wrapper, length):
+def build_ctype(type_, wrapper, length):
     if length is not None:
-        type_ = type_ * length
-    if sys.platform == 'win32' and type_ not in copy_reg.dispatch_table:
-        copy_reg.pickle(type_, reduce_ctype)
-    obj = type_.from_address(wrapper.get_address())
+        obj = (type_ * length).from_address(wrapper.get_address())
+    else:
+        obj = type_.from_address(wrapper.get_address())
     obj._wrapper = wrapper
+    if sys.platform == 'win32':
+        def __reduce_ex__(proto):
+            return build_ctype, (type_, wrapper, length)
+        # It appears that assigning to obj.__reduce_ex__ will override
+        # type(obj).__reduce__, but that assigning to obj.__reduce__ will not.
+        obj.__reduce_ex__ = __reduce_ex__
     return obj
 
 #
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to