Anonymous avatar Anonymous committed f362818

publisher/subscriber cleanup

Comments (0)

Files changed (2)

src/de/matthiasmann/twlscala/Publisher.scala

     def publish(msg:Any) { subscribers.publish(msg) }
     listenTo(this)
     
-    private[twlscala] lazy val subscribers = new SubscriberList
+    private[twlscala] lazy val subscribers = new twlinternal.SubscriberList
 }
 
 final class Reactions {
         list = f :: list
     }
 
-    private var list:List[Reaction] = Nil
+    private[this] var list:List[Reaction] = Nil
     private[twlscala] def handle(msg:Any) {
-        def walkList(l:List[Reaction]):Unit = l match {
-            case r :: rest =>
-                if(r.isDefinedAt(msg)) r(msg)
-                walkList(rest)
-            case _ =>
+        def walkList(l:List[Reaction]):Unit = if(!l.isEmpty) {
+            val r = l.head
+            if(r.isDefinedAt(msg)) r(msg)
+            walkList(l.tail)
         }
         walkList(list)
     }
 }
-
-final private class SubscriberList {
-    import scala.ref.WeakReference
-    type ListType = List[WeakReference[Reactions]]
-    private var list:ListType = Nil
-
-    def += (r:Reactions) { list = new WeakReference(r) :: list}
-    def -= (r:Reactions) {
-        list = list.filter(_.get match {
-            case None    => false
-            case Some(x) => x != r
-        })
-    }
-
-    def publish(msg:Any) {
-        val hasDeadEntries = list.foldLeft(false){(a,b) => b.get match {
-            case Some(r) =>
-                r.handle(msg)
-                a
-            case None =>
-                true
-        }}
-        if(hasDeadEntries) {
-            list = list.filter(!_.get.isEmpty)
-        }
-    }
-}

src/de/matthiasmann/twlscala/twlinternal/SubscriberList.scala

+/*
+ * Copyright (c) 2008-2009, Matthias Mann
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     * Redistributions of source code must retain the above copyright notice,
+ *       this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Matthias Mann nor the names of its contributors may
+ *       be used to endorse or promote products derived from this software
+ *       without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package de.matthiasmann.twlscala.twlinternal
+
+final private[twlscala] class SubscriberList {
+    import scala.ref.WeakReference
+    type ListType = List[WeakReference[Reactions]]
+
+    def += (r:Reactions) { list = new WeakReference(r) :: cleanList}
+    def -= (r:Reactions) {
+        list = list.filter(_.get match {
+            case Some(x) => x ne r
+            case _       => false
+        })
+    }
+
+    def publish(msg:Any) {
+        def walkList(l:ListType, sawDead:Boolean):Boolean =
+        if(l.isEmpty) false else walkList(l.tail, l.head.get match {
+            case Some(r) => r.handle(msg); sawDead
+            case _       => true
+        })
+        if(walkList(list, false)) {
+            list = cleanList
+        }
+    }
+
+    private[this] var list:ListType = Nil
+    private[this] def cleanList = list.filter(!_.get.isEmpty)
+}
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.