PageRenderTime 27ms CodeModel.GetById 22ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/django/contrib/gis/geos/prototypes/threadsafe.py

https://code.google.com/p/mango-py/
Python | 86 lines | 48 code | 16 blank | 22 comment | 5 complexity | 3d798dab7b522d1286e25987821c80fb MD5 | raw file
 1import threading
 2from django.contrib.gis.geos.libgeos import lgeos, notice_h, error_h, CONTEXT_PTR
 3
 4class GEOSContextHandle(object):
 5    """
 6    Python object representing a GEOS context handle.
 7    """
 8    def __init__(self):
 9        # Initializing the context handler for this thread with
10        # the notice and error handler.
11        self.ptr = lgeos.initGEOS_r(notice_h, error_h)
12
13    def __del__(self):
14        if self.ptr: lgeos.finishGEOS_r(self.ptr)
15
16# Defining a thread-local object and creating an instance
17# to hold a reference to GEOSContextHandle for this thread.
18class GEOSContext(threading.local):
19    handle = None
20
21thread_context = GEOSContext()
22
23class GEOSFunc(object):
24    """
25    Class that serves as a wrapper for GEOS C Functions, and will
26    use thread-safe function variants when available.
27    """
28    def __init__(self, func_name):
29        try:
30            # GEOS thread-safe function signatures end with '_r', and
31            # take an additional context handle parameter.
32            self.cfunc = getattr(lgeos, func_name + '_r')
33            self.threaded = True
34            # Create a reference here to thread_context so it's not
35            # garbage-collected before an attempt to call this object.
36            self.thread_context = thread_context
37        except AttributeError:
38            # Otherwise, use usual function.
39            self.cfunc = getattr(lgeos, func_name)
40            self.threaded = False
41
42    def __call__(self, *args):
43        if self.threaded:
44            # If a context handle does not exist for this thread, initialize one.
45            if not self.thread_context.handle:
46                self.thread_context.handle = GEOSContextHandle()
47            # Call the threaded GEOS routine with pointer of the context handle
48            # as the first argument.
49            return self.cfunc(self.thread_context.handle.ptr, *args)
50        else:
51            return self.cfunc(*args)
52
53    def __str__(self):
54        return self.cfunc.__name__
55
56    # argtypes property
57    def _get_argtypes(self):
58        return self.cfunc.argtypes
59
60    def _set_argtypes(self, argtypes):
61        if self.threaded:
62            new_argtypes = [CONTEXT_PTR]
63            new_argtypes.extend(argtypes)
64            self.cfunc.argtypes = new_argtypes
65        else:
66            self.cfunc.argtypes = argtypes
67
68    argtypes = property(_get_argtypes, _set_argtypes)
69
70    # restype property
71    def _get_restype(self):
72        return self.cfunc.restype
73
74    def _set_restype(self, restype):
75        self.cfunc.restype = restype
76
77    restype = property(_get_restype, _set_restype)
78
79    # errcheck property
80    def _get_errcheck(self):
81        return self.cfunc.errcheck
82
83    def _set_errcheck(self, errcheck):
84        self.cfunc.errcheck = errcheck
85
86    errcheck = property(_get_errcheck, _set_errcheck)