/// <summary> /// Constructor called only during FJTaskRunnerGroup initialization /// </summary> protected internal FJTaskRunner(FJTaskRunnerGroup g) { deq = VolatileTaskRef.NewArray(INITIAL_CAPACITY); barrier = new Object(); scanPriority_ = FJTaskRunnerGroup.DefaultScanPriority; group_ = g; victimRNG = new Random(this.GetHashCode()); }
/// <summary> Initialization utility for constructing arrays. /// Make an array of given capacity and fill it with /// VolatileTaskRefs. /// /// </summary> internal static VolatileTaskRef[] NewArray(int cap) { VolatileTaskRef[] a = new VolatileTaskRef[cap]; for (int k = 0; k < cap; k++) { a[k] = new VolatileTaskRef(); } return(a); }
/// <summary> Adjust top and base, and grow DEQ if necessary. /// Called only while DEQ synch lock being held. /// We don't expect this to be called very often. In most /// programs using FJTasks, it is never called. /// /// </summary> protected internal virtual void checkOverflow() { int t = top; int b = base_Renamed; if (t - b < deq.Length - 1) { // check if just need an index reset int newBase = b & (deq.Length - 1); int newTop = top & (deq.Length - 1); if (newTop < newBase) newTop += deq.Length; top = newTop; base_Renamed = newBase; /* Null out refs to stolen tasks. This is the only time we can safely do it. */ int i = newBase; while (i != newTop && deq[i].ref_ != null) { deq[i].ref_ = null; i = (i - 1) & (deq.Length - 1); } } else { // grow by doubling array int newTop = t - b; int oldcap = deq.Length; int newcap = oldcap * 2; if (newcap >= MAX_CAPACITY) throw new ApplicationException("FJTask queue maximum capacity exceeded"); VolatileTaskRef[] newdeq = new VolatileTaskRef[newcap]; // copy in bottom half of new deq with refs from old deq for (int j = 0; j < oldcap; ++j) newdeq[j] = deq[b++ & (oldcap - 1)]; // fill top half of new deq with new refs for (int j = oldcap; j < newcap; ++j) newdeq[j] = new VolatileTaskRef(); deq = newdeq; base_Renamed = 0; top = newTop; } }
/// <summary> Initialization utility for constructing arrays. /// Make an array of given capacity and fill it with /// VolatileTaskRefs. /// /// </summary> internal static VolatileTaskRef[] NewArray(int cap) { VolatileTaskRef[] a = new VolatileTaskRef[cap]; for (int k = 0; k < cap; k++) a[k] = new VolatileTaskRef(); return a; }
/// <summary> Adjust top and base, and grow DEQ if necessary. /// Called only while DEQ synch lock being held. /// We don't expect this to be called very often. In most /// programs using FJTasks, it is never called. /// /// </summary> protected internal virtual void checkOverflow() { int t = top; int b = base_Renamed; if (t - b < deq.Length - 1) { // check if just need an index reset int newBase = b & (deq.Length - 1); int newTop = top & (deq.Length - 1); if (newTop < newBase) { newTop += deq.Length; } top = newTop; base_Renamed = newBase; /* * Null out refs to stolen tasks. * This is the only time we can safely do it. */ int i = newBase; while (i != newTop && deq[i].ref_ != null) { deq[i].ref_ = null; i = (i - 1) & (deq.Length - 1); } } else { // grow by doubling array int newTop = t - b; int oldcap = deq.Length; int newcap = oldcap * 2; if (newcap >= MAX_CAPACITY) { throw new ApplicationException("FJTask queue maximum capacity exceeded"); } VolatileTaskRef[] newdeq = new VolatileTaskRef[newcap]; // copy in bottom half of new deq with refs from old deq for (int j = 0; j < oldcap; ++j) { newdeq[j] = deq[b++ & (oldcap - 1)]; } // fill top half of new deq with new refs for (int j = oldcap; j < newcap; ++j) { newdeq[j] = new VolatileTaskRef(); } deq = newdeq; base_Renamed = 0; top = newTop; } }