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

https://code.google.com/p/mango-py/ · Python · 86 lines · 48 code · 16 blank · 22 comment · 8 complexity · 3d798dab7b522d1286e25987821c80fb MD5 · raw file

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