Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add functions to interrupt processing in a specific thread/context #803

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

dbaston
Copy link
Member

@dbaston dbaston commented Jan 20, 2023

This PR is an alternative API to #761. Instead of registering an interrupt handler for the calling thread -- which is a bit awkward, the handler is registered with the context handle. Since the C++ library has no notion of a context handle, the C API registers and unregisters the interrupt handler with every C API call. To avoid a significant performance penalty for very short C API functions, the C API execute error handler is modified so that functions can be tagged as noninterruptible so the interrupt handler will not be registered when they are called.

- Add Interrupt::requestForCurrentThread (C API: GEOS_interruptThread) to
  request interruption of the current thread only.

- Add Interrupt::registerThreadCallback to register an interruption callback
  for the current thread only.

- Add GEOSContext_setInterruptCallback_r to associate an interruption
  callback with a context handle. The callback will be registered for
  the current thread each time an _r function is called with the
  specified handle.
@dbaston
Copy link
Member Author

dbaston commented Feb 27, 2023

@macdrevx @nyalldawson My understanding is that this API is preferable to #761 for your use cases, but I'm inclined to let this PR sit until you've had a chance to test it (on your own timeline) in case it's difficult to use in a way I didn't anticipate. Does that make sense?

Copy link
Contributor

@macdrevx macdrevx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At a high level, I like this API more than the one in #761. It seems much more natural to consume, and it fits better with my preexisting mental model of the reentrant API.

Comment on lines +340 to +343
extern GEOSInterruptThreadCallback GEOS_DLL *GEOSContext_setInterruptCallback_r(
GEOSContextHandle_t extHandle,
GEOSInterruptThreadCallback* cb,
void* userData);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dbaston what do you think about making this callback return a value that indicates whether an interrupt is desired and eliminating GEOS_interruptThread()?

Comment on lines +330 to +339
* Register a function to be called when a possible interruption point is reached
* in code executed in the specified context. The function can interrupt the
* thread if desired by calling GEOS_interruptThread.
*
* \param extHandle the context returned by \ref GEOS_init_r.
* \param cb Callback function to invoke
* \param userData optional data to be pe provided as argument to callback
* \return the previously registered callback, or NULL
* \see GEOSInterruptThreadCallback
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we say that you should not start other GEOS operations inside of the callback? I ccould imagine folks wanting to make the decision based on the result of some geos operation, but that would risk clobbering the thread_local state used to store the interrupt state.

Comment on lines 52 to +56
void
Interrupt::cancel()
{
requested = false;
requested_for_thread = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cancel() is invoked from GEOS_init_r() — that doesn't seem quite right if we're using it to cancel an interrupt request for a specific context. Does cancellation even make sense for context-specific interruption?

Comment on lines -49 to +62
return requested;
return requested || requested_for_thread;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't there be some synchronization around requested?

* \see GEOS_interruptRegisterThreadCallback
* \see GEOS_interruptThread
*/
typedef void (GEOSInterruptThreadCallback)(void*);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would avoid the word thread in these new APIs and associated documentation. Maybe this one could be named GEOSContextInterruptCallback and similar for other new symbols.

@@ -27,33 +27,55 @@ class GEOS_DLL Interrupt {
public:

typedef void (Callback)(void);
typedef void (ThreadCallback)(void*);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could simplify the design by keeping the old and new implementations separate: We could create a separate class to house the new context-specific interrupt implementation. This would likely also help with my earlier comment about how not all of the API surface that makes sense for the old API is relevant to the new API. My current thinking is that we could update the GEOS_CHECK_FOR_INTERRUPTS() definition to check for interrupts from both sources. Something along the lines of:

#define GEOS_CHECK_FOR_INTERRUPTS() geos::util::Interrupt::process(); geos::util::ThreadSpecificInterrupt::process();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additionally, I think this design would make it easier to one day drop the old interrupt API (something I hope we consider since my main interest in interruption stems from folks who use GEOSwift reporting tooling-detected data races related to the old implementation)

@pramsey
Copy link
Member

pramsey commented Jun 7, 2023

Going to land this or #761 for 3.12?

@dbaston dbaston added this to the 3.13.0 milestone Jun 7, 2023
@robe2
Copy link
Member

robe2 commented Feb 26, 2024

How far are we from landing this in 3.13?

@robe2 robe2 modified the milestones: 3.13.0, 3.14.0 Aug 21, 2024
@nyalldawson
Copy link

Is this waiting on further feedback? I would LOVE to see this land in a geos release soon 🤞

@dbaston
Copy link
Member Author

dbaston commented Aug 26, 2024

@nyalldawson if you're happy with it, then I think all that remains would be to address the good suggestions from @macdrevx . @pramsey , is there a target release date for 3.13?

@nyalldawson
Copy link

@dbaston I like this approach!

@pramsey
Copy link
Member

pramsey commented Aug 27, 2024

is there a target release date for 3.13?

Mid-September. I'd say we're "almost there", so if you feel good about this, merge it and I will roll the next beta, in anticipation of a release after testing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants