mirror of
https://github.com/cookiengineer/audacity
synced 2025-05-02 08:39:46 +02:00
Define CallAfter and Yield in BasicUI...
...so direct uses of wx/app.h may later be removed. That header is one of the files that is in wxBase, but is not acceptable in "toolkit neutral" code, which should not directly use any version of an event loop.
This commit is contained in:
parent
d20cf01255
commit
50e8139716
@ -9,6 +9,9 @@ Paul Licameli
|
||||
**********************************************************************/
|
||||
#include "BasicUI.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
namespace BasicUI {
|
||||
Services::~Services() = default;
|
||||
|
||||
@ -22,4 +25,40 @@ Services *Install(Services *pInstance)
|
||||
theInstance = pInstance;
|
||||
return result;
|
||||
}
|
||||
|
||||
static std::recursive_mutex sActionsMutex;
|
||||
static std::vector<Action> sActions;
|
||||
|
||||
void CallAfter(Action action)
|
||||
{
|
||||
if (auto p = Get())
|
||||
p->DoCallAfter(action);
|
||||
else {
|
||||
// No services yet -- but don't lose the action. Put it in a queue
|
||||
auto guard = std::lock_guard{ sActionsMutex };
|
||||
sActions.emplace_back(std::move(action));
|
||||
}
|
||||
}
|
||||
|
||||
void Yield()
|
||||
{
|
||||
do {
|
||||
// Dispatch anything in the queue, added while there were no Services
|
||||
{
|
||||
auto guard = std::lock_guard{ sActionsMutex };
|
||||
std::vector<Action> actions;
|
||||
actions.swap(sActions);
|
||||
for (auto &action : actions)
|
||||
action();
|
||||
}
|
||||
|
||||
// Dispatch according to Services, if present
|
||||
if (auto p = Get())
|
||||
p->DoYield();
|
||||
}
|
||||
// Re-test for more actions that might have been enqueued by actions just
|
||||
// dispatched
|
||||
while ( !sActions.empty() );
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -11,11 +11,15 @@ Paul Licameli
|
||||
#ifndef __AUDACITY_BASIC_UI__
|
||||
#define __AUDACITY_BASIC_UI__
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace BasicUI {
|
||||
|
||||
//! @name Types used in the Services interface
|
||||
//! @{
|
||||
|
||||
using Action = std::function<void()>;
|
||||
|
||||
//! @}
|
||||
|
||||
//! Abstract class defines a few user interface services, not mentioning particular toolkits
|
||||
@ -25,6 +29,8 @@ namespace BasicUI {
|
||||
class BASIC_UI_API Services {
|
||||
public:
|
||||
virtual ~Services();
|
||||
virtual void DoCallAfter(const Action &action) = 0;
|
||||
virtual void DoYield() = 0;
|
||||
};
|
||||
|
||||
//! Fetch the global instance, or nullptr if none is yet installed
|
||||
@ -40,6 +46,21 @@ BASIC_UI_API Services *Install(Services *pInstance);
|
||||
*/
|
||||
//! @{
|
||||
|
||||
//! Schedule an action to be done later, and in the main thread
|
||||
/*! This function may be called in other threads than the main. If no Services
|
||||
are yet installed, the action is not lost, but may be dispatched by Yield().
|
||||
The action may itself invoke CallAfter to enqueue other actions.
|
||||
*/
|
||||
void CallAfter(Action action);
|
||||
|
||||
//! Dispatch waiting events, including actions enqueued by CallAfter
|
||||
/*! This function must be called by the main thread. Actions enqueued by
|
||||
CallAfter before Services were installed will be dispatched in the sequence
|
||||
they were enqueued, unless an exception thrown by one of them stops the
|
||||
dispatching.
|
||||
*/
|
||||
void Yield();
|
||||
|
||||
//! @}
|
||||
}
|
||||
|
||||
|
@ -8,5 +8,18 @@ Paul Licameli
|
||||
|
||||
**********************************************************************/
|
||||
#include "wxWidgetsBasicUI.h"
|
||||
#include <wx/app.h>
|
||||
|
||||
using namespace BasicUI;
|
||||
|
||||
wxWidgetsBasicUI::~wxWidgetsBasicUI() = default;
|
||||
|
||||
void wxWidgetsBasicUI::DoCallAfter(const Action &action)
|
||||
{
|
||||
wxTheApp->CallAfter(action);
|
||||
}
|
||||
|
||||
void wxWidgetsBasicUI::DoYield()
|
||||
{
|
||||
wxTheApp->Yield();
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ Paul Licameli
|
||||
class wxWidgetsBasicUI final : public BasicUI::Services {
|
||||
public:
|
||||
~wxWidgetsBasicUI() override;
|
||||
|
||||
void DoCallAfter(const BasicUI::Action &action) override;
|
||||
void DoYield() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user