alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Lift Framework example source code file (SoftReferenceCache.scala)

This example Lift Framework source code file (SoftReferenceCache.scala) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Lift Framework tags/keywords

boolean, box, box, empty, int, k, k, referencequeue, softreferencecache, softreferencecache, softvalue, t, util, v, v

The Lift Framework SoftReferenceCache.scala source code

/*
 * Copyright 2007-2011 WorldWide Conferencing, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.liftweb
package util

import java.lang.ref.{ReferenceQueue, SoftReference};
import java.util._
import Map._
import concurrent.locks._

import common._
import util._
import Helpers._
import Schedule._
import java.lang.Thread._


/**
 * Companion module that has the role of monitoring garbage collected references and remove the orphaned
 * keys from the cache. The monitor is started by calling <i>initialize function and terminated by
 * calling <i>shutDown. It monitors all SoftReferenceCache instances in the context of the same classloader.
 * It can also be used as a factory for obtaining new instances of SoftReferenceCache class
 */
object SoftReferenceCache {

  @volatile
  private var terminated = false;

  private[util] val refQueue = new ReferenceQueue[Any]();

  /**
   * Create a new SoftReferenceCache instance
   */
  def apply[K, V](size: Int) = new SoftReferenceCache[K, V](size)

  /**
   * Initialize the orphan keys monitor
   */
  def initialize = {
    // A daemon thread is more approapriate here then an Actor as
    // we'll do blocking reads from the reference queue
    val thread = new Thread(new Runnable() {
      def run() {
        processQueue
      }
    })
    thread.setDaemon(true)
    thread setContextClassLoader null
    thread.start
  }

  /**
   * ShutDown the monitoring
   */
  def shutDown = {
    terminated = true;
  }

  private def processQueue {
    while (!terminated) {
      tryo {
        // Wait 30 seconds for something to appear in the queue.
        val sftVal = refQueue.remove(30000).asInstanceOf[SoftValue[_, _]];
        if (sftVal != null) {
          sftVal.cache.remove(sftVal.key);
        }
      }
    }
  }
}

case object ProcessQueue

case object Done

/**
 * A Map that holds the values as SoftReference-s. It also applies a LRU policy for the cache entries.
 */
class SoftReferenceCache[K, V](cacheSize: Int) {

  val cache = new LinkedHashMap[K, SoftValue[K, V]]() {
    override def removeEldestEntry(eldest: Entry[K, SoftValue[K, V]]): Boolean = {
      return size() > cacheSize;
    }
  }

  val rwl = new ReentrantReadWriteLock();

  val readLock = rwl.readLock
  val writeLock = rwl.writeLock

  private def lock[T](l: Lock)(block: => T): T = {
    l lock;
    try {
      block
    } finally {
      l unlock
    }
  }

  /**
   * Returns the cached value mapped with this key or Empty if not found
   *
   * @param key
   * @return Box[V]
   */
  def apply(key: K): Box[V] = lock(readLock) {
    Box.!!(cache.get(key)) match {
      case Full(value) =>
        Box.!!(value.get) or {
          remove(key);
          Empty
        }
      case _ => Empty
    }
  }

  /**
   * Puts a new keyed entry in cache
   * @param tuple: (K, V)*
   * @return this
   */
  def +=(tuple: (K, V)*) = {
    lock(writeLock) {
      for (t <- tuple) yield {
        cache.put(t._1, new SoftValue(t._1, t._2, this, SoftReferenceCache.refQueue));
      }
    }
    this
  }

  /**
   * Removes the cache entry mapped with this key
   *
   * @returns the value removed
   */
  def remove(key: Any): Box[V] = {
    lock(writeLock) {
      for {value <- Box.!!(cache.remove(key).asInstanceOf[SoftValue[K, V]])
           realValue <- Box.!!(value.get)
      } yield realValue
    }
  }


  def keys = cache.keySet

}

class SoftValue[K, V](k: K,
                      v: V,
                      lruCache: SoftReferenceCache[K, V],
                      queue: ReferenceQueue[Any]) extends SoftReference[V](v, queue) {
  def key: K = k

  def cache: SoftReferenceCache[K, V] = lruCache
}

Other Lift Framework examples (source code examples)

Here is a short list of links related to this Lift Framework SoftReferenceCache.scala source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.