Skip to content

Ported to Dual Class implementation of global objects. #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 47 additions & 41 deletions x10.runtime/src-x10/x10/lang/Clock.x10
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,9 @@ import x10.xrx.Runtime;
* 2.0 style global object by injecting a root field
* that is a GlobalRef(this) and always accessing fields
* as this.root().f instead of this.f.
* TODO: Port to Dual Class implementation of global objects.
*/
public final class Clock(name:String) {
private val root = GlobalRef[Clock](this);
private val root = GlobalRef[LocalClock](new LocalClock());
public def equals(a:Any) {
if (a == null || ! (a instanceof Clock)) {
return false;
Expand All @@ -43,42 +42,14 @@ public final class Clock(name:String) {
public static def make(name:String):Clock {
if (Runtime.STATIC_THREADS) throw new ClockUseException("Clocks are not compatible with static threads.");
val clock = new Clock(name);
getClockPhases().put(clock, FIRST_PHASE);
getClockPhases().put(clock, LocalClock.FIRST_PHASE);
return clock;
}

public static FIRST_PHASE = 1n;
// NOTE: all transient fields must always be accessed as this.root().f (and at place this.root.home),
// not this.f
private transient var count:Int = 1n;
private transient var alive:Int = 1n;
private transient var phase:Int = FIRST_PHASE;

private def this(name:String) {
property(name);
}

// should be accessed through root()
@Pinned private def resumeLocal() {
atomic
if (--alive == 0n) {
alive = count;
++phase;
}
}
// should be accessed through root()
@Pinned private def dropLocal(ph:Int) {
atomic {
--count;
if (-ph != phase) {
if (--alive == 0n) {
alive = count;
++phase;
}
}
}
}

@Global private def get() = getClockPhases().get(this);
@Global private def put(ph:Int) = getClockPhases().put(this, ph);
@Global private def remove() = getClockPhases().remove(this);
Expand All @@ -87,11 +58,7 @@ public final class Clock(name:String) {
val ph = get();
at (root) {
val me = root();
atomic {
++ me.count;
if (-ph != me.phase)
++ me.alive;
}
me.register(ph < 0);
}
return ph;
}
Expand All @@ -101,7 +68,7 @@ public final class Clock(name:String) {
if (ph < 0) return;
at (root) {
val me = root();
me.resumeLocal();
me.resume();
}
put(-ph);
}
Expand All @@ -111,23 +78,23 @@ public final class Clock(name:String) {
val abs = Math.abs(ph);
at (root) {
val me = root();
if (ph > 0) me.resumeLocal();
when (abs < me.phase);
if (ph > 0) me.resume();
me.await(abs);
}
put(abs + 1n);
}
@Global def dropUnsafe() {
val ph = remove();
at(root) {
val me = root();
me.dropLocal(ph);
me.drop(ph < 0);
}
}
@Global def dropInternal() {
val ph = get();
at(root) {
val me = root();
me.dropLocal(ph);
me.drop(ph < 0);
}
}
public @Global def registered():Boolean = getClockPhases().containsKey(this);
Expand Down Expand Up @@ -167,6 +134,45 @@ public final class Clock(name:String) {
@Native("java", "x10.xrx.Runtime.activity().clockPhases()")
private static native def getClockPhases():ClockPhases;

private static class LocalClock {
public static FIRST_PHASE = 1n;
// NOTE: all transient fields must always be accessed as this.root().f (and at place this.root.home),
// not this.f
private transient var count:Int = 1n;
private transient var alive:Int = 1n;
private transient var phase:Int = FIRST_PHASE;

@Pinned public def resume() {
atomic
if (--alive == 0n) {
alive = count;
++phase;
}
}
@Pinned public def drop(resumed:Boolean) {
atomic {
--count;
if (!resumed) {
// a drop serves as a resume
if (--alive == 0n) {
alive = count;
++phase;
}
}
}
}
@Pinned public def register(resumed:Boolean) {
atomic {
++ count;
if (!resumed)
++ alive;
}
}
@Pinned public def await(ph:Int) {
when (ph < phase);
}
}

/**
* Specialization of HashMap to maintain the set of Clocks that
* an Activity is currently registered on.
Expand Down