Shared Objects

This demonstrates an approach to shared objects, and shows how to work with abstract types as well. Note that this is a work-in-progress posted for comment!

package scalax.shared;
 
/** We provide a default shared factory object.
This code is in the public domain.
@author Ross Judson
 
*/
object Shared extends SharedFactory {
}
 
/** A SharedFactory groups shared objects.  Once shared, an object will only
equal itself.  Shared objects are not equal between factories.
*/
class SharedFactory {
  
  import java.util.WeakHashMap;
  import java.lang.ref.WeakReference;
  
  private val objects = new WeakHashMap();
  private var id = 0;
  
  /*
  def build[T <: SharedObject](proto: T): T = synchronized {
    val bo = new BoxedObject(proto);
    val current = objects.get(bo).asInstanceOf[WeakReference];
    var ret: T = null;
    if (current != null) {
      ret = current.get().asInstanceOf[T];
    }
    if (ret == null) {
      proto.setFactory(this);
      objects.put(bo, new WeakReference(proto));
      ret = proto;
    }
    ret
  }
*/
 
  def freshID = synchronized {
    id = id + 1;
    id
  }  
}
 
/** Log prints a message when hashCode or equals is called. */
trait Log {
  abstract override def hashCode() = {
    Console.println(tag + ".hashCode");
    super.hashCode()
  }
  abstract override def equals(o: Any) = {
    Console.println(tag + ".equals");
    super.equals(o);
  }
  def tag: String = getClass().getName();
}
 
/** LogTag extends Log with a custom message instead of printing the class name */
trait LogTag extends Log {
  val logTag: String;
  override def tag = logTag;
}
 
/** FixedHash modifies a class to compute an initial hash value then quickly
return the precomputed hash from then on. */
trait FixedHash {
  private val hash = super.hashCode();
  Console.println("Computed Fixed hash: " + hash);
  abstract override def hashCode() = hash;
  abstract override def equals(o: Any) = o match {
    case fh: FixedHash => hash == fh.hash && super.equals(o)
    case _ => false
  }
}
 
/** A SharedObject is a unique object within a SharedFactory for a given value. */
trait SharedObject {
  /** Returns the factory this shared object is a member of. */
  val factory: SharedFactory;
  /** We override equals to use direct object identity. */
  abstract override def equals(o: Any) = 
    o.isInstanceOf[AnyRef] && (this eq o.asInstanceOf[AnyRef]);
  /** Use the superclass to determine if we are equivalent to another object. */
  def equivalent(o: Any) = super.equals(o);
}
 
/** A Shareable object is an object that can be shared -- this is the "natural"
state for the object.  When duplicate is called, implementers must return a
subclass that further implements FixedHash with SharedObject. */
abstract class Shareable {
 
  // Use an abstract type to identify the self type  
  type This <: Shareable; 
  // Specify the lower bound on the shared type produced by duplication
  type SharedType = This with FixedHash with SharedObject;
  
  // private[shared] unnecessary and unwanted here -- just trying it out.
  private[shared] def duplicate(f: SharedFactory): SharedType;
  private[shared] def duplicate: This = duplicate(Shared);
}
 
 
 
 
/** Some test code. */
object Test extends Application {
  
  abstract class Term extends Shareable;
 
  case class Name(name: String) extends Term {
    override type This = Name;
    // Build shared object with LogTag support.  Note that 
    // "with FixedHash with SharedObject"
    // satisfies the signature for duplicate; we are further blending in the
    // logging support that we want.
    private[shared] def duplicate(f: SharedFactory) = 
      new Name(name) with FixedHash with SharedObject with LogTag {
        val factory = f;
        val logTag = "SharedName";
      }
  }
  
  case class Func(name: String, arity: int) extends Term {
    override type This = Func;
    // Build shared object with regular Log.
    private[shared] def duplicate(f: SharedFactory) = 
      new Func(name, arity) with FixedHash with SharedObject with Log {
        val factory = f;
      }      
  }
  
  // It doesn't look like this will work.  We don't get the abstract override
  // behavior we want.
  trait FSH extends FixedHash with SharedObject with Log;
  case class Var(name: String) extends Term {
    override type This = Var;
    private[shared] def duplicate(f: SharedFactory) = 
      new Var(name) with FSH {
        val factory = f;
      }      
  }
  
  val nameRoss = Name("Ross");
  val funcRoss = Func("Ross", 1);
  val varRoss = Var("Ross");
  
  p(nameRoss);
  p(funcRoss);
  p(varRoss);
  
  def p(t: Term) = {
    val dup = t.duplicate;
    pp(t); 
    pp(dup);
  }
  def pp(t: AnyRef) = 
    Console.println(t.getClass().toString() + 
    " ==> " + t.toString() + ':' + t.hashCode());
  
}
 
code/shared-objects.txt · Last modified: 2008/02/07 15:44 by 207.152.147.19
 
Recent changes RSS feed Valid XHTML 1.0 Driven by DokuWiki