@@ -107,6 +107,20 @@ function geosjl_errorhandler(message::Ptr{UInt8}, userdata)
107107 end
108108end
109109
110+ """
111+
112+ GEOSContext
113+
114+ Every LibGEOS object needs to live somewhere in memory. Also many LibGEOS functions
115+ need scratch memory or caches to do their job.
116+
117+ A `GEOSContext` governs such memory. Almost every function in LibGEOS accepts a `context`
118+ argument, that allows passing a context explicitly. If no context is passed, a global context is used.
119+
120+ Using the global context is fine, as long as no multi threading is used.
121+ If multi threading is used, the global context should be avoided and every operation should only
122+ involve objects that live in the context passed to the operation.
123+ """
110124mutable struct GEOSContext
111125 ptr:: Ptr{Cvoid} # GEOSContextHandle_t
112126
@@ -123,7 +137,7 @@ mutable struct GEOSContext
123137end
124138
125139" Get a copy of a string from GEOS, freeing the GEOS managed memory."
126- function string_copy_free (s:: Cstring , context:: Ptr{Cvoid} = _context . ptr):: String
140+ function string_copy_free (s:: Cstring , context:: Ptr{Cvoid} = get_global_context () . ptr):: String
127141 copy = unsafe_string (s)
128142 GEOSFree_r (context, pointer (s))
129143 return copy
@@ -191,8 +205,50 @@ mutable struct WKBWriter
191205 end
192206end
193207
208+ const _GLOBAL_CONTEXT = Ref {GEOSContext} ()
209+ const _GLOBAL_CONTEXT_ALLOWED = Ref (false )
210+
211+ function get_global_context ():: GEOSContext
212+ if _GLOBAL_CONTEXT_ALLOWED[]
213+ _GLOBAL_CONTEXT[]
214+ else
215+ msg = """
216+ LibGEOS global context disallowed, a `GEOSContext` must be passed explicitly.
217+ Alternatively you can allow the global context by calling:
218+ `LibGEOS.allow_global_context!(true)`
219+ """
220+ error (msg)
221+ end
222+ end
223+
224+ """
225+
226+ allow_global_context!(bool::Bool)
227+
228+ Allow (bool=true) or disallow (bool=false) using the global LibGEOS context.
229+
230+
231+ allow_global_context!(f, bool::Bool)
232+
233+ Call `f` with global context usage allowed according to `bool`
234+
235+ Generally this function should only be used as a debugging tool, mostly for multithreaded programs.
236+ See also [`GEOSContext`](@ref).
237+ """
238+ function allow_global_context! (bool:: Bool )
239+ _GLOBAL_CONTEXT_ALLOWED[] = bool
240+ end
241+
242+ function allow_global_context! (f, bool:: Bool )
243+ old = _GLOBAL_CONTEXT_ALLOWED[]
244+ allow_global_context! (bool)
245+ f ()
246+ allow_global_context! (old)
247+ end
248+
194249function __init__ ()
195- global _context = GEOSContext ()
250+ _GLOBAL_CONTEXT_ALLOWED[] = true
251+ _GLOBAL_CONTEXT[] = GEOSContext ()
196252end
197253
198254include (" geos_functions.jl" )
0 commit comments