diff foosdk/sdk/foobar2000/SDK/abort_callback.h @ 1:20d02a178406 default tip

*: check in everything else yay
author Paper <paper@tflc.us>
date Mon, 05 Jan 2026 02:15:46 -0500
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/foosdk/sdk/foobar2000/SDK/abort_callback.h	Mon Jan 05 02:15:46 2026 -0500
@@ -0,0 +1,140 @@
+#pragma once
+
+namespace foobar2000_io {
+
+PFC_DECLARE_EXCEPTION(exception_aborted,pfc::exception,"User abort");
+
+typedef pfc::eventHandle_t abort_callback_event;
+
+#ifdef check
+#undef check
+#endif
+//! This class is used to signal underlying worker code whether user has decided to abort a potentially time-consuming operation. \n
+//! It is commonly required by all filesystem related or decoding-related operations. \n
+//! Code that receives an abort_callback object should periodically check it and abort any operations being performed if it is signaled, typically throwing exception_aborted. \n
+//! See abort_callback_impl for an implementation.
+class NOVTABLE abort_callback
+{
+public:
+	//! Returns whether user has requested the operation to be aborted.
+	virtual bool is_aborting() const = 0;
+
+	inline bool is_set() const {return is_aborting();}
+
+	//! Retrieves event object that can be used with some OS calls. The even object becomes signaled when abort is triggered. On win32, this is equivalent to win32 event handle (see: CreateEvent). \n
+	//! You must not close this handle or call any methods that change this handle's state (SetEvent() or ResetEvent()), you can only wait for it.
+	virtual abort_callback_event get_abort_event() const = 0;
+
+	inline abort_callback_event get_handle() const {return get_abort_event();}
+	
+	//! Checks if user has requested the operation to be aborted, and throws exception_aborted if so.
+	void check() const;
+
+	//! For compatibility with old code. Do not call.
+	inline void check_e() const {check();}
+
+	
+	//! Sleeps p_timeout_seconds or less when aborted, throws exception_aborted on abort.
+	void sleep(double p_timeout_seconds) const;
+	//! Sleeps p_timeout_seconds or less when aborted, returns true when execution should continue, false when not.
+	bool sleep_ex(double p_timeout_seconds) const;
+	bool sleepNoThrow(double p_timeout_seconds) const { return sleep_ex(p_timeout_seconds); }
+    
+	//! Waits for an event. Returns true if event is now signaled, false if the specified period has elapsed and the event did not become signaled. \n
+	//! Throws exception_aborted if aborted.
+    bool waitForEvent( pfc::eventHandle_t evtHandle, double timeOut ) const;
+	//! Waits for an event. Returns true if event is now signaled, false if the specified period has elapsed and the event did not become signaled. \n
+	//! Throws exception_aborted if aborted.
+	bool waitForEvent(pfc::event& evt, double timeOut) const;
+
+	//! Waits for an event. Returns once the event became signaled; throw exception_aborted if abort occurred first.
+	void waitForEvent(pfc::eventHandle_t evtHandle) const;
+	//! Waits for an event. Returns once the event became signaled; throw exception_aborted if abort occurred first.
+	void waitForEvent(pfc::event& evt) const;
+
+	bool waitForEventNoThrow(pfc::eventHandle_t evt) const;
+	bool waitForEventNoThrow(pfc::event& evt) const;
+
+	abort_callback( const abort_callback & ) = delete;
+	void operator=( const abort_callback & ) = delete;
+protected:
+	abort_callback() {}
+	~abort_callback() {}
+};
+
+
+
+//! Standard implementation of abort_callback interface.
+class abort_callback_impl : public abort_callback {
+public:
+	abort_callback_impl() {}
+	inline void abort() {set_state(true);}
+	inline void set() {set_state(true);}
+	inline void reset() {set_state(false);}
+
+	void set_state(bool p_state) {m_aborting = p_state; m_event.set_state(p_state);}
+
+	bool is_aborting() const override {return m_aborting;}
+
+	abort_callback_event get_abort_event() const override {return m_event.get_handle();}
+
+private:
+	abort_callback_impl(const abort_callback_impl &) = delete;
+	const abort_callback_impl & operator=(const abort_callback_impl&) = delete;
+	
+	volatile bool m_aborting = false;
+	pfc::event m_event;
+};
+
+//! Alternate abort_callback implementation, supply your own event handle to signal abort. \n
+//! Slightly less efficient (is_aborting() polls the event instead of reading a bool variable).
+class abort_callback_usehandle : public abort_callback {
+public:
+    abort_callback_usehandle( abort_callback_event handle ) : m_handle(handle) {}
+    
+    bool is_aborting() const override;
+    abort_callback_event get_abort_event() const override { return m_handle; }
+protected:
+    const abort_callback_event m_handle;
+};
+
+class abort_callback_clone : public abort_callback_usehandle {
+public:
+	abort_callback_clone(abort_callback_event handle) : abort_callback_usehandle(clone(handle)) {}
+	abort_callback_clone(abort_callback & arg) : abort_callback_usehandle(clone(arg.get_handle())) {}
+	~abort_callback_clone() { close(m_handle); }
+
+	static abort_callback_event clone(abort_callback_event);
+	static void close(abort_callback_event);
+};
+
+//! Dummy abort_callback that never gets aborted. \n
+//! Note that there's no need to create instances of it, use shared fb2k::noAbort object instead.
+class abort_callback_dummy : public abort_callback {
+public:
+	bool is_aborting() const override { return false; }
+
+	abort_callback_event get_abort_event() const override { return m_event;}
+private:
+	const abort_callback_event m_event = GetInfiniteWaitEvent();
+};
+
+}
+typedef foobar2000_io::abort_callback_event fb2k_event_handle;
+typedef foobar2000_io::abort_callback fb2k_event;
+typedef foobar2000_io::abort_callback_impl fb2k_event_impl;
+
+using namespace foobar2000_io;
+
+#define FB2K_PFCv2_ABORTER_SCOPE( abortObj ) \
+    (abortObj).check(); \
+    PP::waitableReadRef_t aborterRef = {(abortObj).get_abort_event()}; \
+    PP::aborter aborter_pfcv2( aborterRef );    \
+    PP::aborterScope l_aborterScope( aborter_pfcv2 );
+
+
+namespace fb2k {
+	//! A shared abort_callback_dummy instance. \n
+	//! Use when some function requires an abort_callback& and you don't have one: somefunc(fb2k::noAbort);
+	extern abort_callback_dummy noAbort;
+}