Mercurial > foo_out_sdl
diff foosdk/sdk/foobar2000/helpers/callInMainThreadHelper.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/helpers/callInMainThreadHelper.h Mon Jan 05 02:15:46 2026 -0500 @@ -0,0 +1,127 @@ +#pragma once +#include <SDK/main_thread_callback.h> + +// ====================================================================================================== +// Obsolete helpers - they still work, but it's easier to just use fb2k::inMainThread(). +// ====================================================================================================== + + +// Proxy class - friend this to allow callInMainThread to access your private methods +class callInMainThread { +public: + template<typename host_t, typename param_t> + static void callThis(host_t * host, param_t & param) { + host->inMainThread(param); + } + template<typename host_t> + static void callThis( host_t * host ) { + host->inMainThread(); + } +}; + +// Internal class, do not use. +template<typename service_t, typename param_t> +class _callInMainThreadSvc_t : public main_thread_callback { +public: + _callInMainThreadSvc_t(service_t * host, param_t const & param) : m_host(host), m_param(param) {} + void callback_run() { + callInMainThread::callThis(m_host.get_ptr(), m_param); + } +private: + service_ptr_t<service_t> m_host; + param_t m_param; +}; + + +// Main thread callback helper. You can use this to easily invoke inMainThread(someparam) on your class without writing any wrapper code. +// Requires myservice_t to be a fb2k service class with reference counting. +template<typename myservice_t, typename param_t> +static void callInMainThreadSvc(myservice_t * host, param_t const & param) { + typedef _callInMainThreadSvc_t<myservice_t, param_t> impl_t; + service_ptr_t<impl_t> obj = new service_impl_t<impl_t>(host, param); + main_thread_callback_manager::get()->add_callback( obj ); +} + +//! Helper class to call methods of your class (host class) in main thread with convenience. \n +//! Deals with the otherwise ugly scenario of your class becoming invalid while a method is queued. \n +//! Have this as a member of your class, then use m_mthelper.add( this, somearg ) ; to defer a call to this->inMainThread(somearg). \n +//! If your class becomes invalid before inMainThread is executed, the pending callback is discarded. \n +//! You can optionally call shutdown() to invalidate all pending callbacks early (in a destructor of your class - without waiting for callInMainThreadHelper destructor to do the job. \n +//! In order to let callInMainThreadHelper access your private methods, declare friend class callInMainThread. \n +//! Note that callInMainThreadHelper is expected to be created and destroyed in main thread. +class callInMainThreadHelper { +public: + + typedef std::function< void () > func_t; + + typedef pfc::rcptr_t< bool > killswitch_t; + + class entryFunc : public main_thread_callback { + public: + entryFunc( func_t const & func, killswitch_t ks ) : m_ks(ks), m_func(func) {} + + void callback_run() { + if (!*m_ks) m_func(); + } + + private: + killswitch_t m_ks; + func_t m_func; + }; + + template<typename host_t, typename arg_t> + class entry : public main_thread_callback { + public: + entry( host_t * host, arg_t const & arg, killswitch_t ks ) : m_ks(ks), m_host(host), m_arg(arg) {} + void callback_run() { + if (!*m_ks) callInMainThread::callThis( m_host, m_arg ); + } + private: + killswitch_t m_ks; + host_t * m_host; + arg_t m_arg; + }; + template<typename host_t> + class entryVoid : public main_thread_callback { + public: + entryVoid( host_t * host, killswitch_t ks ) : m_ks(ks), m_host(host) {} + void callback_run() { + if (!*m_ks) callInMainThread::callThis( m_host ); + } + private: + killswitch_t m_ks; + host_t * m_host; + }; + + void add(func_t f) { + add_( new service_impl_t< entryFunc > ( f, m_ks ) ); + } + + template<typename host_t, typename arg_t> + void add( host_t * host, arg_t const & arg) { + add_( new service_impl_t< entry<host_t, arg_t> >( host, arg, m_ks ) ); + } + template<typename host_t> + void add( host_t * host ) { + add_( new service_impl_t< entryVoid<host_t> >( host, m_ks ) ); + } + void add_( main_thread_callback::ptr cb ) { + main_thread_callback_add( cb ); + } + + callInMainThreadHelper() { + m_ks.new_t(); + * m_ks = false; + } + void shutdown() { + PFC_ASSERT( core_api::is_main_thread() ); + * m_ks = true; + } + ~callInMainThreadHelper() { + shutdown(); + } + +private: + killswitch_t m_ks; + +};
