comparison 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
comparison
equal deleted inserted replaced
0:e9bb126753e7 1:20d02a178406
1 #pragma once
2
3 namespace foobar2000_io {
4
5 PFC_DECLARE_EXCEPTION(exception_aborted,pfc::exception,"User abort");
6
7 typedef pfc::eventHandle_t abort_callback_event;
8
9 #ifdef check
10 #undef check
11 #endif
12 //! This class is used to signal underlying worker code whether user has decided to abort a potentially time-consuming operation. \n
13 //! It is commonly required by all filesystem related or decoding-related operations. \n
14 //! 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
15 //! See abort_callback_impl for an implementation.
16 class NOVTABLE abort_callback
17 {
18 public:
19 //! Returns whether user has requested the operation to be aborted.
20 virtual bool is_aborting() const = 0;
21
22 inline bool is_set() const {return is_aborting();}
23
24 //! 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
25 //! 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.
26 virtual abort_callback_event get_abort_event() const = 0;
27
28 inline abort_callback_event get_handle() const {return get_abort_event();}
29
30 //! Checks if user has requested the operation to be aborted, and throws exception_aborted if so.
31 void check() const;
32
33 //! For compatibility with old code. Do not call.
34 inline void check_e() const {check();}
35
36
37 //! Sleeps p_timeout_seconds or less when aborted, throws exception_aborted on abort.
38 void sleep(double p_timeout_seconds) const;
39 //! Sleeps p_timeout_seconds or less when aborted, returns true when execution should continue, false when not.
40 bool sleep_ex(double p_timeout_seconds) const;
41 bool sleepNoThrow(double p_timeout_seconds) const { return sleep_ex(p_timeout_seconds); }
42
43 //! 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
44 //! Throws exception_aborted if aborted.
45 bool waitForEvent( pfc::eventHandle_t evtHandle, double timeOut ) const;
46 //! 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
47 //! Throws exception_aborted if aborted.
48 bool waitForEvent(pfc::event& evt, double timeOut) const;
49
50 //! Waits for an event. Returns once the event became signaled; throw exception_aborted if abort occurred first.
51 void waitForEvent(pfc::eventHandle_t evtHandle) const;
52 //! Waits for an event. Returns once the event became signaled; throw exception_aborted if abort occurred first.
53 void waitForEvent(pfc::event& evt) const;
54
55 bool waitForEventNoThrow(pfc::eventHandle_t evt) const;
56 bool waitForEventNoThrow(pfc::event& evt) const;
57
58 abort_callback( const abort_callback & ) = delete;
59 void operator=( const abort_callback & ) = delete;
60 protected:
61 abort_callback() {}
62 ~abort_callback() {}
63 };
64
65
66
67 //! Standard implementation of abort_callback interface.
68 class abort_callback_impl : public abort_callback {
69 public:
70 abort_callback_impl() {}
71 inline void abort() {set_state(true);}
72 inline void set() {set_state(true);}
73 inline void reset() {set_state(false);}
74
75 void set_state(bool p_state) {m_aborting = p_state; m_event.set_state(p_state);}
76
77 bool is_aborting() const override {return m_aborting;}
78
79 abort_callback_event get_abort_event() const override {return m_event.get_handle();}
80
81 private:
82 abort_callback_impl(const abort_callback_impl &) = delete;
83 const abort_callback_impl & operator=(const abort_callback_impl&) = delete;
84
85 volatile bool m_aborting = false;
86 pfc::event m_event;
87 };
88
89 //! Alternate abort_callback implementation, supply your own event handle to signal abort. \n
90 //! Slightly less efficient (is_aborting() polls the event instead of reading a bool variable).
91 class abort_callback_usehandle : public abort_callback {
92 public:
93 abort_callback_usehandle( abort_callback_event handle ) : m_handle(handle) {}
94
95 bool is_aborting() const override;
96 abort_callback_event get_abort_event() const override { return m_handle; }
97 protected:
98 const abort_callback_event m_handle;
99 };
100
101 class abort_callback_clone : public abort_callback_usehandle {
102 public:
103 abort_callback_clone(abort_callback_event handle) : abort_callback_usehandle(clone(handle)) {}
104 abort_callback_clone(abort_callback & arg) : abort_callback_usehandle(clone(arg.get_handle())) {}
105 ~abort_callback_clone() { close(m_handle); }
106
107 static abort_callback_event clone(abort_callback_event);
108 static void close(abort_callback_event);
109 };
110
111 //! Dummy abort_callback that never gets aborted. \n
112 //! Note that there's no need to create instances of it, use shared fb2k::noAbort object instead.
113 class abort_callback_dummy : public abort_callback {
114 public:
115 bool is_aborting() const override { return false; }
116
117 abort_callback_event get_abort_event() const override { return m_event;}
118 private:
119 const abort_callback_event m_event = GetInfiniteWaitEvent();
120 };
121
122 }
123 typedef foobar2000_io::abort_callback_event fb2k_event_handle;
124 typedef foobar2000_io::abort_callback fb2k_event;
125 typedef foobar2000_io::abort_callback_impl fb2k_event_impl;
126
127 using namespace foobar2000_io;
128
129 #define FB2K_PFCv2_ABORTER_SCOPE( abortObj ) \
130 (abortObj).check(); \
131 PP::waitableReadRef_t aborterRef = {(abortObj).get_abort_event()}; \
132 PP::aborter aborter_pfcv2( aborterRef ); \
133 PP::aborterScope l_aborterScope( aborter_pfcv2 );
134
135
136 namespace fb2k {
137 //! A shared abort_callback_dummy instance. \n
138 //! Use when some function requires an abort_callback& and you don't have one: somefunc(fb2k::noAbort);
139 extern abort_callback_dummy noAbort;
140 }