latest SDK
This commit is contained in:
119
foobar2000/SDK/abort_callback.h
Normal file
119
foobar2000/SDK/abort_callback.h
Normal file
@@ -0,0 +1,119 @@
|
||||
#ifndef _foobar2000_sdk_abort_callback_h_
|
||||
#define _foobar2000_sdk_abort_callback_h_
|
||||
|
||||
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;
|
||||
|
||||
//! 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 );
|
||||
//! 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);
|
||||
|
||||
//! Waits for an event. Returns once the event became signaled; throw exception_aborted if abort occurred first.
|
||||
void waitForEvent(pfc::eventHandle_t evtHandle);
|
||||
//! Waits for an event. Returns once the event became signaled; throw exception_aborted if abort occurred first.
|
||||
void waitForEvent(pfc::event& evt);
|
||||
protected:
|
||||
abort_callback() {}
|
||||
~abort_callback() {}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! Implementation of abort_callback interface.
|
||||
class abort_callback_impl : public abort_callback {
|
||||
public:
|
||||
abort_callback_impl() : m_aborting(false) {}
|
||||
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 {return m_aborting;}
|
||||
|
||||
abort_callback_event get_abort_event() const {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;
|
||||
pfc::event m_event;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
//! Dummy abort_callback that never gets aborted. \n
|
||||
//! Slightly more efficient than the regular one especially when you need to regularly create temporary instances of it.
|
||||
class abort_callback_dummy : public abort_callback {
|
||||
public:
|
||||
bool is_aborting() const { return false; }
|
||||
|
||||
abort_callback_event get_abort_event() const { return GetInfiniteWaitEvent();}
|
||||
};
|
||||
#else
|
||||
|
||||
// FIX ME come up with a scheme to produce a persistent infinite wait filedescriptor on non Windows
|
||||
// Could use /dev/null but still need to open it on upon object creation which defeats the purpose
|
||||
typedef abort_callback_impl abort_callback_dummy;
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
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
|
||||
extern abort_callback_dummy noAbort;
|
||||
}
|
||||
|
||||
#endif //_foobar2000_sdk_abort_callback_h_
|
||||
Reference in New Issue
Block a user