1edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
2edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Module which supports allocation of ctypes objects from shared memory
3edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
4edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# multiprocessing/sharedctypes.py
5edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
6edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Copyright (c) 2006-2008, R Oudkerk
7edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# All rights reserved.
8edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
9edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Redistribution and use in source and binary forms, with or without
10edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# modification, are permitted provided that the following conditions
11edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# are met:
12edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
13edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# 1. Redistributions of source code must retain the above copyright
14edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#    notice, this list of conditions and the following disclaimer.
15edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# 2. Redistributions in binary form must reproduce the above copyright
16edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#    notice, this list of conditions and the following disclaimer in the
17edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#    documentation and/or other materials provided with the distribution.
18edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# 3. Neither the name of author nor the names of any contributors may be
19edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#    used to endorse or promote products derived from this software
20edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#    without specific prior written permission.
21edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
22edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
23edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# SUCH DAMAGE.
33edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
34edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
35edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport sys
36edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport ctypes
37edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepimport weakref
38edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
39edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom multiprocessing import heap, RLock
40edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepfrom multiprocessing.forking import assert_spawning, ForkingPickler
41edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
42edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep__all__ = ['RawValue', 'RawArray', 'Value', 'Array', 'copy', 'synchronized']
43edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
44edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
45edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
46edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
47edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
48edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoeptypecode_to_type = {
49edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    'c': ctypes.c_char,  'u': ctypes.c_wchar,
50edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    'b': ctypes.c_byte,  'B': ctypes.c_ubyte,
51edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    'h': ctypes.c_short, 'H': ctypes.c_ushort,
52edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    'i': ctypes.c_int,   'I': ctypes.c_uint,
53edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    'l': ctypes.c_long,  'L': ctypes.c_ulong,
54edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    'f': ctypes.c_float, 'd': ctypes.c_double
55edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    }
56edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
57edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
58edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
59edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
60edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
61edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef _new_value(type_):
62edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    size = ctypes.sizeof(type_)
63edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    wrapper = heap.BufferWrapper(size)
64edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    return rebuild_ctype(type_, wrapper, None)
65edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
66edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef RawValue(typecode_or_type, *args):
67edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    '''
68edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    Returns a ctypes object allocated from shared memory
69edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    '''
70edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    type_ = typecode_to_type.get(typecode_or_type, typecode_or_type)
71edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    obj = _new_value(type_)
72edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    ctypes.memset(ctypes.addressof(obj), 0, ctypes.sizeof(obj))
73edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    obj.__init__(*args)
74edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    return obj
75edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
76edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef RawArray(typecode_or_type, size_or_initializer):
77edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    '''
78edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    Returns a ctypes array allocated from shared memory
79edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    '''
80edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    type_ = typecode_to_type.get(typecode_or_type, typecode_or_type)
81edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if isinstance(size_or_initializer, (int, long)):
82edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        type_ = type_ * size_or_initializer
83edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        obj = _new_value(type_)
84edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        ctypes.memset(ctypes.addressof(obj), 0, ctypes.sizeof(obj))
85edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return obj
86edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    else:
87edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        type_ = type_ * len(size_or_initializer)
88edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        result = _new_value(type_)
89edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        result.__init__(*size_or_initializer)
90edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return result
91edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
92edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef Value(typecode_or_type, *args, **kwds):
93edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    '''
94edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    Return a synchronization wrapper for a Value
95edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    '''
96edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    lock = kwds.pop('lock', None)
97edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if kwds:
98edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        raise ValueError('unrecognized keyword argument(s): %s' % kwds.keys())
99edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    obj = RawValue(typecode_or_type, *args)
100edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if lock is False:
101edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return obj
102edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if lock in (True, None):
103edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        lock = RLock()
104edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if not hasattr(lock, 'acquire'):
105edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        raise AttributeError("'%r' has no method 'acquire'" % lock)
106edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    return synchronized(obj, lock)
107edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
108edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef Array(typecode_or_type, size_or_initializer, **kwds):
109edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    '''
110edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    Return a synchronization wrapper for a RawArray
111edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    '''
112edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    lock = kwds.pop('lock', None)
113edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if kwds:
114edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        raise ValueError('unrecognized keyword argument(s): %s' % kwds.keys())
115edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    obj = RawArray(typecode_or_type, size_or_initializer)
116edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if lock is False:
117edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return obj
118edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if lock in (True, None):
119edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        lock = RLock()
120edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if not hasattr(lock, 'acquire'):
121edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        raise AttributeError("'%r' has no method 'acquire'" % lock)
122edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    return synchronized(obj, lock)
123edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
124edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef copy(obj):
125edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    new_obj = _new_value(type(obj))
126edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    ctypes.pointer(new_obj)[0] = obj
127edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    return new_obj
128edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
129edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef synchronized(obj, lock=None):
130edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    assert not isinstance(obj, SynchronizedBase), 'object already synchronized'
131edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
132edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if isinstance(obj, ctypes._SimpleCData):
133edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return Synchronized(obj, lock)
134edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    elif isinstance(obj, ctypes.Array):
135edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        if obj._type_ is ctypes.c_char:
136edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            return SynchronizedString(obj, lock)
137edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return SynchronizedArray(obj, lock)
138edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    else:
139edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        cls = type(obj)
140edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        try:
141edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            scls = class_cache[cls]
142edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        except KeyError:
143edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            names = [field[0] for field in cls._fields_]
144edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            d = dict((name, make_property(name)) for name in names)
145edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            classname = 'Synchronized' + cls.__name__
146edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            scls = class_cache[cls] = type(classname, (SynchronizedBase,), d)
147edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return scls(obj, lock)
148edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
149edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
150edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Functions for pickling/unpickling
151edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
152edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
153edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef reduce_ctype(obj):
154edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    assert_spawning(obj)
155edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if isinstance(obj, ctypes.Array):
156edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return rebuild_ctype, (obj._type_, obj._wrapper, obj._length_)
157edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    else:
158edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return rebuild_ctype, (type(obj), obj._wrapper, None)
159edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
160edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef rebuild_ctype(type_, wrapper, length):
161edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    if length is not None:
162edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        type_ = type_ * length
163edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    ForkingPickler.register(type_, reduce_ctype)
164edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    obj = type_.from_address(wrapper.get_address())
165edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    obj._wrapper = wrapper
166edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    return obj
167edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
168edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
169edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Function to create properties
170edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
171edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
172edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef make_property(name):
173edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    try:
174edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return prop_cache[name]
175edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    except KeyError:
176edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        d = {}
177edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        exec template % ((name,)*7) in d
178edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        prop_cache[name] = d[name]
179edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return d[name]
180edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
181edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoeptemplate = '''
182edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef get%s(self):
183edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    self.acquire()
184edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    try:
185edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return self._obj.%s
186edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    finally:
187edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.release()
188edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepdef set%s(self, value):
189edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    self.acquire()
190edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    try:
191edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self._obj.%s = value
192edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    finally:
193edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.release()
194edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep%s = property(get%s, set%s)
195edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep'''
196edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
197edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepprop_cache = {}
198edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass_cache = weakref.WeakKeyDictionary()
199edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
200edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
201edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep# Synchronized wrappers
202edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep#
203edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
204edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass SynchronizedBase(object):
205edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
206edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def __init__(self, obj, lock=None):
207edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self._obj = obj
208edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self._lock = lock or RLock()
209edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.acquire = self._lock.acquire
210edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.release = self._lock.release
211edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
212edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def __reduce__(self):
213edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        assert_spawning(self)
214edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return synchronized, (self._obj, self._lock)
215edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
216edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def get_obj(self):
217edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return self._obj
218edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
219edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def get_lock(self):
220edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return self._lock
221edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
222edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def __repr__(self):
223edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return '<%s wrapper for %s>' % (type(self).__name__, self._obj)
224edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
225edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
226edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass Synchronized(SynchronizedBase):
227edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    value = make_property('value')
228edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
229edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
230edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass SynchronizedArray(SynchronizedBase):
231edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
232edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def __len__(self):
233edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        return len(self._obj)
234edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
235edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def __getitem__(self, i):
236edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.acquire()
237edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        try:
238edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            return self._obj[i]
239edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        finally:
240edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self.release()
241edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
242edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def __setitem__(self, i, value):
243edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.acquire()
244edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        try:
245edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self._obj[i] = value
246edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        finally:
247edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self.release()
248edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
249edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def __getslice__(self, start, stop):
250edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.acquire()
251edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        try:
252edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            return self._obj[start:stop]
253edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        finally:
254edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self.release()
255edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
256edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    def __setslice__(self, start, stop, values):
257edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        self.acquire()
258edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        try:
259edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self._obj[start:stop] = values
260edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep        finally:
261edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep            self.release()
262edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
263edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep
264edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoepclass SynchronizedString(SynchronizedArray):
265edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    value = make_property('value')
266edbb763a2b63074cd468a5d33a17908b2cc0654Jeff Vander Stoep    raw = make_property('raw')
267