From 1a887cda634e87b9b09dd33d7ab32d7685172666 Mon Sep 17 00:00:00 2001 From: Julian Storer Date: Fri, 17 Dec 2010 21:24:36 +0000 Subject: [PATCH] Fix for AsyncUpdaters. --- juce_amalgamated.cpp | 24 +++++++++++++----------- juce_amalgamated.h | 19 +++++++++++++++++-- src/events/juce_AsyncUpdater.cpp | 18 ++++++++---------- src/events/juce_AsyncUpdater.h | 6 ++++-- src/events/juce_CallbackMessage.h | 14 ++++++++++++++ src/events/juce_MessageManager.cpp | 7 +++++-- 6 files changed, 61 insertions(+), 27 deletions(-) diff --git a/juce_amalgamated.cpp b/juce_amalgamated.cpp index 92c9f3b113..ed525ceae7 100644 --- a/juce_amalgamated.cpp +++ b/juce_amalgamated.cpp @@ -38422,6 +38422,7 @@ public: AsyncUpdaterMessage (AsyncUpdater& owner_) : owner (owner_) { + setMessageIsDeletedOnDelivery (false); } void messageCallback() @@ -38430,10 +38431,12 @@ public: owner.handleAsyncUpdate(); } +private: AsyncUpdater& owner; }; -AsyncUpdater::AsyncUpdater() throw() +AsyncUpdater::AsyncUpdater() + : message (new AsyncUpdaterMessage (*this)) { } @@ -38445,18 +38448,14 @@ AsyncUpdater::~AsyncUpdater() // deleting this object, or find some other way to avoid such a race condition. jassert ((! isUpdatePending()) || MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - pendingMessage = 0; + if (pendingMessage.exchange (0) != 0) + message.release()->setMessageIsDeletedOnDelivery (true); } void AsyncUpdater::triggerAsyncUpdate() { - if (pendingMessage.value == 0) - { - ScopedPointer pending (new AsyncUpdaterMessage (*this)); - - if (pendingMessage.compareAndSetBool (pending, 0)) - pending.release()->post(); - } + if (pendingMessage.compareAndSetBool (message, 0)) + message->post(); } void AsyncUpdater::cancelPendingUpdate() throw() @@ -39092,7 +39091,7 @@ void MessageManager::postMessageToQueue (Message* const message) delete message; } -CallbackMessage::CallbackMessage() throw() {} +CallbackMessage::CallbackMessage() throw() : deleteOnDelivery (true) {} CallbackMessage::~CallbackMessage() {} void CallbackMessage::post() @@ -39106,7 +39105,7 @@ void MessageManager::deliverMessage (Message* const message) { JUCE_TRY { - const ScopedPointer messageDeleter (message); + ScopedPointer messageDeleter (message); MessageListener* const recipient = message->messageRecipient; if (recipient == 0) @@ -39116,6 +39115,9 @@ void MessageManager::deliverMessage (Message* const message) if (callbackMessage != 0) { callbackMessage->messageCallback(); + + if (! callbackMessage->isMessageDeletedOnDelivery()) + messageDeleter.release(); } else if (message->intParameter1 == quitMessageId) { diff --git a/juce_amalgamated.h b/juce_amalgamated.h index 70deb5a7d0..f209aead28 100644 --- a/juce_amalgamated.h +++ b/juce_amalgamated.h @@ -12490,7 +12490,7 @@ class JUCE_API AsyncUpdater public: /** Creates an AsyncUpdater object. */ - AsyncUpdater() throw(); + AsyncUpdater(); /** Destructor. @@ -12544,7 +12544,8 @@ private: class AsyncUpdaterMessage; friend class AsyncUpdaterMessage; - + friend class ScopedPointer; + ScopedPointer message; Atomic pendingMessage; }; @@ -43823,8 +43824,22 @@ public: */ void post(); + /** This can be used to indicate whether the MessageManager should delete the + message after it has been delivered. + By default, messages will be deleted, but you might want to disable this so that you + can re-use the same message. + */ + void setMessageIsDeletedOnDelivery (bool shouldBeDeleted) throw() { deleteOnDelivery = shouldBeDeleted; } + + /** Returns true if the message should be deleted after is has been delivered. + @see setMessageIsDeletedOnDelivery + */ + bool isMessageDeletedOnDelivery() const throw() { return deleteOnDelivery; } + private: + bool deleteOnDelivery; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallbackMessage); }; diff --git a/src/events/juce_AsyncUpdater.cpp b/src/events/juce_AsyncUpdater.cpp index d4200beff5..0176b7a96a 100644 --- a/src/events/juce_AsyncUpdater.cpp +++ b/src/events/juce_AsyncUpdater.cpp @@ -29,7 +29,6 @@ BEGIN_JUCE_NAMESPACE #include "juce_AsyncUpdater.h" #include "juce_CallbackMessage.h" -#include "../containers/juce_ScopedPointer.h" #include "juce_MessageManager.h" @@ -40,6 +39,7 @@ public: AsyncUpdaterMessage (AsyncUpdater& owner_) : owner (owner_) { + setMessageIsDeletedOnDelivery (false); } void messageCallback() @@ -48,11 +48,13 @@ public: owner.handleAsyncUpdate(); } +private: AsyncUpdater& owner; }; //============================================================================== -AsyncUpdater::AsyncUpdater() throw() +AsyncUpdater::AsyncUpdater() + : message (new AsyncUpdaterMessage (*this)) { } @@ -64,18 +66,14 @@ AsyncUpdater::~AsyncUpdater() // deleting this object, or find some other way to avoid such a race condition. jassert ((! isUpdatePending()) || MessageManager::getInstance()->currentThreadHasLockedMessageManager()); - pendingMessage = 0; + if (pendingMessage.exchange (0) != 0) + message.release()->setMessageIsDeletedOnDelivery (true); } void AsyncUpdater::triggerAsyncUpdate() { - if (pendingMessage.value == 0) - { - ScopedPointer pending (new AsyncUpdaterMessage (*this)); - - if (pendingMessage.compareAndSetBool (pending, 0)) - pending.release()->post(); - } + if (pendingMessage.compareAndSetBool (message, 0)) + message->post(); } void AsyncUpdater::cancelPendingUpdate() throw() diff --git a/src/events/juce_AsyncUpdater.h b/src/events/juce_AsyncUpdater.h index 2b108bbe37..54af442083 100644 --- a/src/events/juce_AsyncUpdater.h +++ b/src/events/juce_AsyncUpdater.h @@ -27,6 +27,7 @@ #define __JUCE_ASYNCUPDATER_JUCEHEADER__ #include "../core/juce_Atomic.h" +#include "../containers/juce_ScopedPointer.h" //============================================================================== @@ -44,7 +45,7 @@ class JUCE_API AsyncUpdater public: //============================================================================== /** Creates an AsyncUpdater object. */ - AsyncUpdater() throw(); + AsyncUpdater(); /** Destructor. @@ -101,7 +102,8 @@ private: //============================================================================== class AsyncUpdaterMessage; friend class AsyncUpdaterMessage; - + friend class ScopedPointer; + ScopedPointer message; Atomic pendingMessage; }; diff --git a/src/events/juce_CallbackMessage.h b/src/events/juce_CallbackMessage.h index 8cc8d0ed01..fb0d4bc422 100644 --- a/src/events/juce_CallbackMessage.h +++ b/src/events/juce_CallbackMessage.h @@ -73,8 +73,22 @@ public: */ void post(); + /** This can be used to indicate whether the MessageManager should delete the + message after it has been delivered. + By default, messages will be deleted, but you might want to disable this so that you + can re-use the same message. + */ + void setMessageIsDeletedOnDelivery (bool shouldBeDeleted) throw() { deleteOnDelivery = shouldBeDeleted; } + + /** Returns true if the message should be deleted after is has been delivered. + @see setMessageIsDeletedOnDelivery + */ + bool isMessageDeletedOnDelivery() const throw() { return deleteOnDelivery; } + private: //============================================================================== + bool deleteOnDelivery; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CallbackMessage); }; diff --git a/src/events/juce_MessageManager.cpp b/src/events/juce_MessageManager.cpp index 7e7c56df65..1614cd9206 100644 --- a/src/events/juce_MessageManager.cpp +++ b/src/events/juce_MessageManager.cpp @@ -88,7 +88,7 @@ void MessageManager::postMessageToQueue (Message* const message) } //============================================================================== -CallbackMessage::CallbackMessage() throw() {} +CallbackMessage::CallbackMessage() throw() : deleteOnDelivery (true) {} CallbackMessage::~CallbackMessage() {} void CallbackMessage::post() @@ -103,7 +103,7 @@ void MessageManager::deliverMessage (Message* const message) { JUCE_TRY { - const ScopedPointer messageDeleter (message); + ScopedPointer messageDeleter (message); MessageListener* const recipient = message->messageRecipient; if (recipient == 0) @@ -113,6 +113,9 @@ void MessageManager::deliverMessage (Message* const message) if (callbackMessage != 0) { callbackMessage->messageCallback(); + + if (! callbackMessage->isMessageDeletedOnDelivery()) + messageDeleter.release(); } else if (message->intParameter1 == quitMessageId) {