ยปCore Development>Code coverage>Lib/multiprocessing/sharedctypes.py

Python code coverage for Lib/multiprocessing/sharedctypes.py

#countcontent
1n/a#
2n/a# Module which supports allocation of ctypes objects from shared memory
3n/a#
4n/a# multiprocessing/sharedctypes.py
5n/a#
6n/a# Copyright (c) 2006-2008, R Oudkerk
7n/a# Licensed to PSF under a Contributor Agreement.
8n/a#
9n/a
10n/aimport ctypes
11n/aimport weakref
12n/a
13n/afrom . import heap
14n/afrom . import get_context
15n/a
16n/afrom .context import reduction, assert_spawning
17n/a_ForkingPickler = reduction.ForkingPickler
18n/a
19n/a__all__ = ['RawValue', 'RawArray', 'Value', 'Array', 'copy', 'synchronized']
20n/a
21n/a#
22n/a#
23n/a#
24n/a
25n/atypecode_to_type = {
26n/a 'c': ctypes.c_char, 'u': ctypes.c_wchar,
27n/a 'b': ctypes.c_byte, 'B': ctypes.c_ubyte,
28n/a 'h': ctypes.c_short, 'H': ctypes.c_ushort,
29n/a 'i': ctypes.c_int, 'I': ctypes.c_uint,
30n/a 'l': ctypes.c_long, 'L': ctypes.c_ulong,
31n/a 'f': ctypes.c_float, 'd': ctypes.c_double
32n/a }
33n/a
34n/a#
35n/a#
36n/a#
37n/a
38n/adef _new_value(type_):
39n/a size = ctypes.sizeof(type_)
40n/a wrapper = heap.BufferWrapper(size)
41n/a return rebuild_ctype(type_, wrapper, None)
42n/a
43n/adef RawValue(typecode_or_type, *args):
44n/a '''
45n/a Returns a ctypes object allocated from shared memory
46n/a '''
47n/a type_ = typecode_to_type.get(typecode_or_type, typecode_or_type)
48n/a obj = _new_value(type_)
49n/a ctypes.memset(ctypes.addressof(obj), 0, ctypes.sizeof(obj))
50n/a obj.__init__(*args)
51n/a return obj
52n/a
53n/adef RawArray(typecode_or_type, size_or_initializer):
54n/a '''
55n/a Returns a ctypes array allocated from shared memory
56n/a '''
57n/a type_ = typecode_to_type.get(typecode_or_type, typecode_or_type)
58n/a if isinstance(size_or_initializer, int):
59n/a type_ = type_ * size_or_initializer
60n/a obj = _new_value(type_)
61n/a ctypes.memset(ctypes.addressof(obj), 0, ctypes.sizeof(obj))
62n/a return obj
63n/a else:
64n/a type_ = type_ * len(size_or_initializer)
65n/a result = _new_value(type_)
66n/a result.__init__(*size_or_initializer)
67n/a return result
68n/a
69n/adef Value(typecode_or_type, *args, lock=True, ctx=None):
70n/a '''
71n/a Return a synchronization wrapper for a Value
72n/a '''
73n/a obj = RawValue(typecode_or_type, *args)
74n/a if lock is False:
75n/a return obj
76n/a if lock in (True, None):
77n/a ctx = ctx or get_context()
78n/a lock = ctx.RLock()
79n/a if not hasattr(lock, 'acquire'):
80n/a raise AttributeError("'%r' has no method 'acquire'" % lock)
81n/a return synchronized(obj, lock, ctx=ctx)
82n/a
83n/adef Array(typecode_or_type, size_or_initializer, *, lock=True, ctx=None):
84n/a '''
85n/a Return a synchronization wrapper for a RawArray
86n/a '''
87n/a obj = RawArray(typecode_or_type, size_or_initializer)
88n/a if lock is False:
89n/a return obj
90n/a if lock in (True, None):
91n/a ctx = ctx or get_context()
92n/a lock = ctx.RLock()
93n/a if not hasattr(lock, 'acquire'):
94n/a raise AttributeError("'%r' has no method 'acquire'" % lock)
95n/a return synchronized(obj, lock, ctx=ctx)
96n/a
97n/adef copy(obj):
98n/a new_obj = _new_value(type(obj))
99n/a ctypes.pointer(new_obj)[0] = obj
100n/a return new_obj
101n/a
102n/adef synchronized(obj, lock=None, ctx=None):
103n/a assert not isinstance(obj, SynchronizedBase), 'object already synchronized'
104n/a ctx = ctx or get_context()
105n/a
106n/a if isinstance(obj, ctypes._SimpleCData):
107n/a return Synchronized(obj, lock, ctx)
108n/a elif isinstance(obj, ctypes.Array):
109n/a if obj._type_ is ctypes.c_char:
110n/a return SynchronizedString(obj, lock, ctx)
111n/a return SynchronizedArray(obj, lock, ctx)
112n/a else:
113n/a cls = type(obj)
114n/a try:
115n/a scls = class_cache[cls]
116n/a except KeyError:
117n/a names = [field[0] for field in cls._fields_]
118n/a d = dict((name, make_property(name)) for name in names)
119n/a classname = 'Synchronized' + cls.__name__
120n/a scls = class_cache[cls] = type(classname, (SynchronizedBase,), d)
121n/a return scls(obj, lock, ctx)
122n/a
123n/a#
124n/a# Functions for pickling/unpickling
125n/a#
126n/a
127n/adef reduce_ctype(obj):
128n/a assert_spawning(obj)
129n/a if isinstance(obj, ctypes.Array):
130n/a return rebuild_ctype, (obj._type_, obj._wrapper, obj._length_)
131n/a else:
132n/a return rebuild_ctype, (type(obj), obj._wrapper, None)
133n/a
134n/adef rebuild_ctype(type_, wrapper, length):
135n/a if length is not None:
136n/a type_ = type_ * length
137n/a _ForkingPickler.register(type_, reduce_ctype)
138n/a buf = wrapper.create_memoryview()
139n/a obj = type_.from_buffer(buf)
140n/a obj._wrapper = wrapper
141n/a return obj
142n/a
143n/a#
144n/a# Function to create properties
145n/a#
146n/a
147n/adef make_property(name):
148n/a try:
149n/a return prop_cache[name]
150n/a except KeyError:
151n/a d = {}
152n/a exec(template % ((name,)*7), d)
153n/a prop_cache[name] = d[name]
154n/a return d[name]
155n/a
156n/atemplate = '''
157n/adef get%s(self):
158n/a self.acquire()
159n/a try:
160n/a return self._obj.%s
161n/a finally:
162n/a self.release()
163n/adef set%s(self, value):
164n/a self.acquire()
165n/a try:
166n/a self._obj.%s = value
167n/a finally:
168n/a self.release()
169n/a%s = property(get%s, set%s)
170n/a'''
171n/a
172n/aprop_cache = {}
173n/aclass_cache = weakref.WeakKeyDictionary()
174n/a
175n/a#
176n/a# Synchronized wrappers
177n/a#
178n/a
179n/aclass SynchronizedBase(object):
180n/a
181n/a def __init__(self, obj, lock=None, ctx=None):
182n/a self._obj = obj
183n/a if lock:
184n/a self._lock = lock
185n/a else:
186n/a ctx = ctx or get_context(force=True)
187n/a self._lock = ctx.RLock()
188n/a self.acquire = self._lock.acquire
189n/a self.release = self._lock.release
190n/a
191n/a def __enter__(self):
192n/a return self._lock.__enter__()
193n/a
194n/a def __exit__(self, *args):
195n/a return self._lock.__exit__(*args)
196n/a
197n/a def __reduce__(self):
198n/a assert_spawning(self)
199n/a return synchronized, (self._obj, self._lock)
200n/a
201n/a def get_obj(self):
202n/a return self._obj
203n/a
204n/a def get_lock(self):
205n/a return self._lock
206n/a
207n/a def __repr__(self):
208n/a return '<%s wrapper for %s>' % (type(self).__name__, self._obj)
209n/a
210n/a
211n/aclass Synchronized(SynchronizedBase):
212n/a value = make_property('value')
213n/a
214n/a
215n/aclass SynchronizedArray(SynchronizedBase):
216n/a
217n/a def __len__(self):
218n/a return len(self._obj)
219n/a
220n/a def __getitem__(self, i):
221n/a with self:
222n/a return self._obj[i]
223n/a
224n/a def __setitem__(self, i, value):
225n/a with self:
226n/a self._obj[i] = value
227n/a
228n/a def __getslice__(self, start, stop):
229n/a with self:
230n/a return self._obj[start:stop]
231n/a
232n/a def __setslice__(self, start, stop, values):
233n/a with self:
234n/a self._obj[start:stop] = values
235n/a
236n/a
237n/aclass SynchronizedString(SynchronizedArray):
238n/a value = make_property('value')
239n/a raw = make_property('raw')