You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

threadsafe.py 2.3KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. import threading
  2. from django.contrib.gis.geos.base import GEOSBase
  3. from django.contrib.gis.geos.libgeos import (
  4. CONTEXT_PTR, error_h, lgeos, notice_h,
  5. )
  6. class GEOSContextHandle(GEOSBase):
  7. """Represent a GEOS context handle."""
  8. ptr_type = CONTEXT_PTR
  9. destructor = lgeos.finishGEOS_r
  10. def __init__(self):
  11. # Initializing the context handler for this thread with
  12. # the notice and error handler.
  13. self.ptr = lgeos.initGEOS_r(notice_h, error_h)
  14. # Defining a thread-local object and creating an instance
  15. # to hold a reference to GEOSContextHandle for this thread.
  16. class GEOSContext(threading.local):
  17. handle = None
  18. thread_context = GEOSContext()
  19. class GEOSFunc:
  20. """
  21. Serve as a wrapper for GEOS C Functions. Use thread-safe function
  22. variants when available.
  23. """
  24. def __init__(self, func_name):
  25. # GEOS thread-safe function signatures end with '_r' and take an
  26. # additional context handle parameter.
  27. self.cfunc = getattr(lgeos, func_name + '_r')
  28. # Create a reference to thread_context so it's not garbage-collected
  29. # before an attempt to call this object.
  30. self.thread_context = thread_context
  31. def __call__(self, *args):
  32. # Create a context handle if one doesn't exist for this thread.
  33. self.thread_context.handle = self.thread_context.handle or GEOSContextHandle()
  34. # Call the threaded GEOS routine with the pointer of the context handle
  35. # as the first argument.
  36. return self.cfunc(self.thread_context.handle.ptr, *args)
  37. def __str__(self):
  38. return self.cfunc.__name__
  39. # argtypes property
  40. def _get_argtypes(self):
  41. return self.cfunc.argtypes
  42. def _set_argtypes(self, argtypes):
  43. self.cfunc.argtypes = [CONTEXT_PTR, *argtypes]
  44. argtypes = property(_get_argtypes, _set_argtypes)
  45. # restype property
  46. def _get_restype(self):
  47. return self.cfunc.restype
  48. def _set_restype(self, restype):
  49. self.cfunc.restype = restype
  50. restype = property(_get_restype, _set_restype)
  51. # errcheck property
  52. def _get_errcheck(self):
  53. return self.cfunc.errcheck
  54. def _set_errcheck(self, errcheck):
  55. self.cfunc.errcheck = errcheck
  56. errcheck = property(_get_errcheck, _set_errcheck)