summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationQueue.java
diff options
context:
space:
mode:
authorBenjamin Culkin <scorpress@gmail.com>2024-05-19 17:56:33 -0400
committerBenjamin Culkin <scorpress@gmail.com>2024-05-19 17:56:33 -0400
commitaedc34d55462a75e329bbf342251ff6504cd117e (patch)
treebcc8f1f2352582717b484df302aeea6696b8f000 /projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationQueue.java
Initial import from SVN
Diffstat (limited to 'projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationQueue.java')
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationQueue.java345
1 files changed, 345 insertions, 0 deletions
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationQueue.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationQueue.java
new file mode 100644
index 0000000..7350a39
--- /dev/null
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationQueue.java
@@ -0,0 +1,345 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2001 Intersect Software Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.foundation;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+* NSNotificationQueue coalesces notifications to be
+* posted to the NSNotificationCenter and can post them
+* asynchronously. While calling postNotification on
+* the notification center does not return until all
+* receivers have been notified, calling enqueueNotification
+* can return immediately. Use this class when you want
+* to coalesce notifications or notify asynchronously, or
+* both, which is the typical case.
+*
+* @author michael@mpowers.net
+* @author $Author: cgruber $
+* @version $Revision: 893 $
+*/
+public class NSNotificationQueue
+{
+ private static NSNotificationQueue defaultQueue = null;
+
+ /**
+ * Posting style specifying that the notification should
+ * be posted on the next available event loop.
+ */
+ public static final int PostASAP = 4;
+
+ /**
+ * Posting style specifying that the notification should
+ * be posted on the next available idle loop.
+ */
+ public static final int PostWhenIdle = 8;
+
+ /**
+ * Posting style specifying that the notification should
+ * be posted immediately. The enqueue method will not
+ * return until all receivers have been notified.
+ */
+ public static final int PostNow = 16;
+
+ /**
+ * Used to indicate that this notification should not
+ * be coalesced with other notifications.
+ * Ignored if combined with other coalesce flags.
+ */
+ public static final int NotificationNoCoalescing = 0;
+
+ /**
+ * Used to indicate that this notification should
+ * be coalesced with other notifications with the
+ * same name.
+ * May be combined with NotificationCoalescingOnSender.
+ */
+ public static final int NotificationCoalescingOnName = 1;
+
+ /**
+ * Used to indicate that this notification should
+ * be coalesced with other notifications with the
+ * same object argument (which is typically the sender).
+ * May be combined with NotificationCoalescingOnName.
+ */
+ public static final int NotificationCoalescingOnSender = 2;
+
+ /**
+ * The ASAP queue, which should probably use a LinkedList.
+ */
+ private List queue;
+
+ /**
+ * The idle queue, which should probably use a LinkedList.
+ */
+ private List idleQueue;
+
+ /**
+ * The notification center we will be using.
+ */
+ private NSNotificationCenter center;
+
+ /**
+ * Our private ASAP notifier.
+ */
+ private Notifier notifier;
+
+ /**
+ * Our private idle notifier.
+ */
+ private Notifier idleNotifier;
+
+ /**
+ * Default constructor creates a new notification queue
+ * that uses the default notification center.
+ */
+ public NSNotificationQueue()
+ {
+ this( NSNotificationCenter.defaultCenter() );
+ }
+
+ /**
+ * Creates a new notification queue that uses the
+ * specified notification center.
+ */
+ public NSNotificationQueue(
+ NSNotificationCenter aCenter )
+ {
+ queue = new LinkedList();
+ idleQueue = new LinkedList();
+ center = aCenter;
+ notifier = new Notifier( this, queue );
+ idleNotifier = new Notifier( this, idleQueue );
+ }
+
+ /**
+ * Returns the system default queue, creating one
+ * if it has not yet been created. The system default
+ * queue uses the system default notification center.
+ */
+ static public NSNotificationQueue defaultQueue()
+ {
+ if ( defaultQueue == null )
+ {
+ defaultQueue = new NSNotificationQueue();
+ }
+ return defaultQueue;
+ }
+
+ /**
+ * Removes notifications from the queue that match
+ * the specified notification, considering the
+ * specified coalesce mask.
+ */
+ public void dequeueMatchingNotifications(
+ NSNotification aNotification,
+ int aCoalesceMask)
+ {
+ if ( aCoalesceMask == NotificationNoCoalescing ) return;
+ dequeueFromQueue( aNotification, aCoalesceMask, queue );
+ dequeueFromQueue( aNotification, aCoalesceMask, idleQueue );
+ }
+
+ private void dequeueFromQueue(
+ NSNotification aNotification,
+ int aCoalesceMask,
+ List aQueue )
+ {
+ synchronized ( aQueue )
+ {
+ int flag;
+ NSNotification notification;
+ Object name = aNotification.name();
+ Object object = aNotification.object();
+ Iterator it = aQueue.iterator();
+ while ( it.hasNext() )
+ {
+ flag = 0;
+ notification = (NSNotification) it.next();
+ // if NotificationCoalescingOnName
+ if ( ( aCoalesceMask == 1 ) || ( aCoalesceMask == 3 ) )
+ {
+ if ( name == null )
+ {
+ if ( notification.name() != null )
+ {
+ flag += NotificationCoalescingOnName;
+ }
+ }
+ else
+ {
+ // compare by value
+ if ( name.equals( notification.name() ) )
+ {
+ flag += NotificationCoalescingOnName;
+ }
+ }
+ }
+ // if NotificationCoalescingOnSender
+ if ( aCoalesceMask >= 2 )
+ {
+ // compare by reference
+ if ( object == notification.object() )
+ {
+ flag += NotificationCoalescingOnSender;
+ }
+ }
+
+ if ( flag == aCoalesceMask )
+ {
+ it.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Adds the notification to the queue to be run at
+ * the time specified by the posting style. The
+ * notification will be coalesced with other notifications
+ * that match the same name and object (sender) argument.
+ */
+ public void enqueueNotification(
+ NSNotification aNotification,
+ int aPostingStyle)
+ {
+ enqueueNotificationWithCoalesceMaskForModes(
+ aNotification, aPostingStyle,
+ NotificationCoalescingOnName + NotificationCoalescingOnSender,
+ null );
+ }
+
+ /**
+ * Adds the notification to the queue to be run at
+ * the time specified by the posting style and coelesced
+ * as the specified mask indicates.
+ * aModeList is currently ignored and may be null.
+ */
+ public void enqueueNotificationWithCoalesceMaskForModes(
+ NSNotification aNotification,
+ int aPostingStyle,
+ int aCoalesceMask,
+ List aModeList)
+ {
+ dequeueMatchingNotifications( aNotification, aCoalesceMask );
+
+ if ( aPostingStyle == PostNow )
+ {
+ center.postNotification( aNotification );
+ return;
+ }
+
+ if ( aPostingStyle == PostASAP )
+ {
+ synchronized ( queue )
+ {
+ queue.add( aNotification );
+ if ( ! notifier.willRun )
+ {
+ // asap runs at the very first run loop ordering, plus one just in case
+ NSRunLoop.invokeLaterWithOrder( notifier, 1 );
+ notifier.willRun = true;
+ }
+ }
+ return;
+ }
+
+ if ( aPostingStyle == PostWhenIdle )
+ {
+ synchronized ( idleQueue )
+ {
+ idleQueue.add( aNotification );
+ if ( ! idleNotifier.willRun )
+ {
+ // when idle runs at the very last run loop ordering, minus one just in case
+ NSRunLoop.invokeLaterWithOrder( idleNotifier, Integer.MAX_VALUE - 1 );
+ idleNotifier.willRun = true;
+ }
+ }
+ return;
+ }
+
+ }
+
+ private class Notifier implements Runnable
+ {
+ public boolean willRun;
+
+ NSNotificationQueue parent;
+ List queue;
+
+ public Notifier(
+ NSNotificationQueue aParent, List aQueue )
+ {
+ willRun = false;
+ parent = aParent;
+ queue = aQueue;
+ }
+
+ public void run()
+ {
+ Iterator it = new LinkedList( queue ).iterator();
+ synchronized ( queue )
+ {
+ queue.clear();
+ }
+ willRun = false;
+
+ // queue must already be cleared and willRun reset
+ // because this loop might queue more notifications
+ while ( it.hasNext() )
+ {
+ parent.center.postNotification(
+ (NSNotification) it.next() );
+ }
+ }
+ }
+
+}
+
+/*
+ * $Log$
+ * Revision 1.2 2006/02/16 13:15:00 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.6 2003/08/11 18:18:08 chochos
+ * improved encoding of strings, removed warnings
+ *
+ * Revision 1.5 2003/08/06 23:07:52 chochos
+ * general code cleanup (mostly, removing unused imports)
+ *
+ * Revision 1.4 2001/11/01 15:49:26 mpowers
+ * With NSRunLoop, we can now correctly implement PostASAP and PostWhenIdle.
+ *
+ * Revision 1.3 2001/06/25 14:47:24 mpowers
+ * Fixed serious error where some notifications were not being posted at all.
+ * A simple change to Notifier class fixed the problem. Thanks to glista.
+ *
+ * Revision 1.2 2001/02/26 15:53:22 mpowers
+ * Fine-tuning notification firing.
+ * Child display groups now update properly after parent save or invalidate.
+ *
+ * Revision 1.1 2001/02/24 17:03:22 mpowers
+ * Implemented the notification queue, and changed editing context to use it.
+ *
+ *
+ */
+