|
- /*
- ==============================================================================
-
- This file is part of the JUCE library.
- Copyright (c) 2022 - Raw Material Software Limited
-
- JUCE is an open source library subject to commercial or open-source
- licensing.
-
- The code included in this file is provided under the terms of the ISC license
- http://www.isc.org/downloads/software-support-policy/isc-license. Permission
- To use, copy, modify, and/or distribute this software for any purpose with or
- without fee is hereby granted provided that the above copyright notice and
- this permission notice appear in all copies.
-
- JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
- EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
- DISCLAIMED.
-
- ==============================================================================
- */
-
- namespace juce
- {
-
- class AsyncUpdater::AsyncUpdaterMessage : public CallbackMessage
- {
- public:
- AsyncUpdaterMessage (AsyncUpdater& au) : owner (au) {}
-
- void messageCallback() override
- {
- if (shouldDeliver.compareAndSetBool (0, 1))
- owner.handleAsyncUpdate();
- }
-
- AsyncUpdater& owner;
- Atomic<int> shouldDeliver;
-
- JUCE_DECLARE_NON_COPYABLE (AsyncUpdaterMessage)
- };
-
- //==============================================================================
- AsyncUpdater::AsyncUpdater()
- {
- activeMessage = *new AsyncUpdaterMessage (*this);
- }
-
- AsyncUpdater::~AsyncUpdater()
- {
- // You're deleting this object with a background thread while there's an update
- // pending on the main event thread - that's pretty dodgy threading, as the callback could
- // happen after this destructor has finished. You should either use a MessageManagerLock while
- // deleting this object, or find some other way to avoid such a race condition.
- jassert ((! isUpdatePending())
- || MessageManager::getInstanceWithoutCreating() == nullptr
- || MessageManager::getInstanceWithoutCreating()->currentThreadHasLockedMessageManager());
-
- activeMessage->shouldDeliver.set (0);
- }
-
- void AsyncUpdater::triggerAsyncUpdate()
- {
- // If you're calling this before (or after) the MessageManager is
- // running, then you're not going to get any callbacks!
- JUCE_ASSERT_MESSAGE_MANAGER_EXISTS
-
- if (activeMessage->shouldDeliver.compareAndSetBool (1, 0))
- if (! activeMessage->post())
- cancelPendingUpdate(); // if the message queue fails, this avoids getting
- // trapped waiting for the message to arrive
- }
-
- void AsyncUpdater::cancelPendingUpdate() noexcept
- {
- activeMessage->shouldDeliver.set (0);
- }
-
- void AsyncUpdater::handleUpdateNowIfNeeded()
- {
- // This can only be called by the event thread.
- JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED
-
- if (activeMessage->shouldDeliver.exchange (0) != 0)
- handleAsyncUpdate();
- }
-
- bool AsyncUpdater::isUpdatePending() const noexcept
- {
- return activeMessage->shouldDeliver.value != 0;
- }
-
- } // namespace juce
|