summaryrefslogtreecommitdiff
path: root/src/library
diff options
context:
space:
mode:
authorAleksandar Pokopec <aleksandar.prokopec@epfl.ch>2010-01-14 17:02:45 +0000
committerAleksandar Pokopec <aleksandar.prokopec@epfl.ch>2010-01-14 17:02:45 +0000
commiteaa949005f8bf28d563d347755c07e96c2866e87 (patch)
tree49d9166af1b8d8ea657d44dbd429b6b917b96611 /src/library
parent9693cd5c2b92b0a322070fab24b51bbe1a080722 (diff)
downloadscala-eaa949005f8bf28d563d347755c07e96c2866e87.tar.gz
scala-eaa949005f8bf28d563d347755c07e96c2866e87.tar.bz2
scala-eaa949005f8bf28d563d347755c07e96c2866e87.zip
ConcurrentMap trait added to collection.mutable.
JavaConversions now include conversions between Java ConcurrentMap objects and Scala ConcurrentMap objects. review by odersky
Diffstat (limited to 'src/library')
-rw-r--r--src/library/scala/collection/JavaConversions.scala71
-rw-r--r--src/library/scala/collection/mutable/ConcurrentMap.scala79
2 files changed, 148 insertions, 2 deletions
diff --git a/src/library/scala/collection/JavaConversions.scala b/src/library/scala/collection/JavaConversions.scala
index 7d05227336..7af138067b 100644
--- a/src/library/scala/collection/JavaConversions.scala
+++ b/src/library/scala/collection/JavaConversions.scala
@@ -179,10 +179,17 @@ object JavaConversions {
* @return A Java <code>Map</code> view of the argument.
*/
implicit def asMap[A, B](m : mutable.Map[A, B])(implicit ma : ClassManifest[A]) : ju.Map[A, B] = m match {
+ //case JConcurrentMapWrapper(wrapped) => wrapped
case JMapWrapper(wrapped) => wrapped
case _ => new MutableMapWrapper(m)(ma)
}
+ implicit def asConcurrentMap[A, B](m: mutable.ConcurrentMap[A, B])
+ (implicit ma: ClassManifest[A], mb: ClassManifest[B]): juc.ConcurrentMap[A, B] = m match {
+ case JConcurrentMapWrapper(wrapped) => wrapped
+ case _ => new ConcurrentMapWrapper(m)(ma, mb)
+ }
+
// Java => Scala
/**
@@ -304,11 +311,26 @@ object JavaConversions {
* @return A Scala mutable <code>Map</code> view of the argument.
*/
implicit def asMap[A, B](m : ju.Map[A, B]) = m match {
+ //case ConcurrentMapWrapper(wrapped) => wrapped
case MutableMapWrapper(wrapped) => wrapped
case _ => new JMapWrapper(m)
}
+ /**
+ * Implicitly converts a Java <code>ConcurrentMap</code> to a Scala mutable <code>ConcurrentMap</code>.
+ * The returned Scala <code>ConcurrentMap</code> is backed by the provided Java
+ * <code>ConcurrentMap</code> and any side-effects of using it via the Scala interface will
+ * be visible via the Java interface and vice versa.
+ * <p>
+ * If the Java <code>ConcurrentMap</code> was previously obtained from an implicit or
+ * explicit call of <code>asConcurrentMap(scala.collection.mutable.ConcurrentMap)</code> then the original
+ * Scala <code>ConcurrentMap</code> will be returned.
+ *
+ * @param m The <code>ConcurrentMap</code> to be converted.
+ * @return A Scala mutable <code>ConcurrrentMap</code> view of the argument.
+ */
implicit def asConcurrentMap[A, B](m: juc.ConcurrentMap[A, B]) = m match {
+ case ConcurrentMapWrapper(wrapped) => wrapped
case _ => new JConcurrentMapWrapper(m)
}
@@ -419,7 +441,8 @@ object JavaConversions {
override def empty = JSetWrapper(new ju.HashSet[A])
}
- case class MutableMapWrapper[A, B](underlying : mutable.Map[A, B])(m : ClassManifest[A]) extends ju.AbstractMap[A, B] {
+ abstract class MutableMapWrapperLike[A, B](underlying: mutable.Map[A, B])(m: ClassManifest[A])
+ extends ju.AbstractMap[A, B] {
self =>
override def size = underlying.size
@@ -471,6 +494,9 @@ object JavaConversions {
}
}
+ case class MutableMapWrapper[A, B](underlying : mutable.Map[A, B])(m : ClassManifest[A])
+ extends MutableMapWrapperLike[A, B](underlying)(m)
+
abstract class JMapWrapperLike[A, B, +Repr <: mutable.MapLike[A, B, Repr] with mutable.Map[A, B]]
(underlying: ju.Map[A, B])
extends mutable.Map[A, B] with mutable.MapLike[A, B, Repr] {
@@ -517,8 +543,49 @@ object JavaConversions {
override def empty = JMapWrapper(new ju.HashMap[A, B])
}
+ case class ConcurrentMapWrapper[A, B](underlying: mutable.ConcurrentMap[A, B])
+ (m: ClassManifest[A], mv: ClassManifest[B])
+ extends MutableMapWrapperLike[A, B](underlying)(m) with juc.ConcurrentMap[A, B] {
+ self =>
+
+ override def remove(k : AnyRef) = {
+ if (!m.erasure.isInstance(k))
+ null.asInstanceOf[B]
+ else {
+ val k1 = k.asInstanceOf[A]
+ underlying.remove(k1) match {
+ case Some(v) => v
+ case None => null.asInstanceOf[B]
+ }
+ }
+ }
+
+ def putIfAbsent(k: A, v: B) = underlying.putIfAbsent(k, v) match {
+ case Some(v) => v
+ case None => null.asInstanceOf[B]
+ }
+
+ def remove(k: AnyRef, v: AnyRef) = {
+ if (!m.erasure.isInstance(k) || !mv.erasure.isInstance(v))
+ false
+ else {
+ val k1 = k.asInstanceOf[A]
+ val v1 = v.asInstanceOf[B]
+ underlying.remove(k1, v1)
+ }
+ }
+
+ def replace(k: A, v: B): B = underlying.replace(k, v) match {
+ case Some(v) => v
+ case None => null.asInstanceOf[B]
+ }
+
+ def replace(k: A, oldval: B, newval: B) = underlying.replace(k, oldval, newval)
+
+ }
+
case class JConcurrentMapWrapper[A, B](underlying: juc.ConcurrentMap[A, B])
- extends JMapWrapperLike[A, B, JConcurrentMapWrapper[A, B]](underlying) {
+ extends JMapWrapperLike[A, B, JConcurrentMapWrapper[A, B]](underlying) with mutable.ConcurrentMap[A, B] {
override def get(k: A) = {
val v = underlying.get(k)
if (v != null) Some(v)
diff --git a/src/library/scala/collection/mutable/ConcurrentMap.scala b/src/library/scala/collection/mutable/ConcurrentMap.scala
new file mode 100644
index 0000000000..d09bf57e1b
--- /dev/null
+++ b/src/library/scala/collection/mutable/ConcurrentMap.scala
@@ -0,0 +1,79 @@
+package scala.collection.mutable
+
+
+
+
+
+
+/**
+ * A template trait for mutable maps that allow concurrent access.
+ * $concurrentmapinfo
+ *
+ * @tparam A the key type of the map
+ * @tparam B the value type of the map
+ *
+ * @define concurrentmapinfo
+ * This is a base trait for all Scala concurrent map implementations. It
+ * provides all of the methods a Map does, with the difference that all the
+ * changes are atomic. It also describes methods specific to concurrent maps.
+ * Note: The concurrent maps do not accept `null` for keys or values.
+ *
+ * @define atomicop
+ * This is done atomically.
+ *
+ * @since 2.8
+ */
+trait ConcurrentMap[A, B] extends Map[A, B] {
+
+ /**
+ * Associates the given key with a given value, unless the key was already associated with some other value.
+ * $atomicop
+ *
+ * @param k key with which the specified value is to be associated with
+ * @param v value to be associated with the specified key
+ * @return `Some(oldvalue)` if there was a value `oldvalue` previously associated with the
+ * specified key, or `None` if there was no mapping for the specified key
+ */
+ def putIfAbsent(k: A, v: B): Option[B]
+
+ /**
+ * Removes the entry for the specified key if its currently mapped to the specified value.
+ * $atomicop
+ *
+ * @param k key for which the entry should be removed
+ * @param v value expected to be associated with the specified key if the removal is to take place
+ * @return `true` if the removal took place, `false` otherwise
+ */
+ def remove(k: A, v: B): Boolean
+
+ /**
+ * Replaces the entry for the given key only if it was previously mapped to a given value.
+ * $atomicop
+ *
+ * @param k key for which the entry should be replaced
+ * @param oldvalue value expected to be associated with the specified key if replacing is to happen
+ * @param newvalue value to be associated with the specified key
+ * @return `true` if the entry was replaced, `false` otherwise
+ */
+ def replace(k: A, oldvalue: B, newvalue: B): Boolean
+
+ /**
+ * Replaces the entry for the given key only if it was previously mapped to some value.
+ * $atomicop
+ *
+ * @param k key for which the entry should be replaced
+ * @param v value to be associated with the specified key
+ * @return `Some(v)` if the given key was previously mapped to some value `v`, or `None` otherwise
+ */
+ def replace(k: A, v: B): Option[B]
+
+}
+
+
+
+
+
+
+
+
+