public void EvalGawk(RCRunner runner, RCClosure closure, RCSymbol symbol, RCLong right) { int limit = (int)right[0]; lock (_readWriteLock) { Section s = GetSection(symbol); ReadSpec spec = s._counter.GetReadSpec(symbol, limit, false, true); Satisfy canSatisfy = s._counter.CanSatisfy(spec); RCCube result = s._blackboard.Read(spec, s._counter, true, s._blackboard.Count); if ((spec.SymbolUnlimited && result.Count > 0) || (!spec.SymbolUnlimited && result.Count >= symbol.Count * Math.Abs(spec.SymbolLimit))) { if (canSatisfy != Satisfy.Yes) { throw new Exception(); } runner.Yield(closure, result); } else { if (canSatisfy != Satisfy.No) { throw new Exception(); } s._dispatchWaiters.Enqueue(symbol, closure); } } }
public void EvalPage(RCRunner runner, RCClosure closure, RCSymbol symbol, RCLong right) { int pageNumber = 0; if (right.Count > 0) { pageNumber = (int)right[0]; } int pageSize = int.MaxValue; if (right.Count > 1) { pageSize = (int)right[1]; } // Page lets you access the blackboard by page number and page size, rather than row // numbers. // Good for building tools for looking at blackboard contents. lock (_readWriteLock) { Section s = GetSection(symbol); int skipFirst = pageNumber * pageSize; int stopAfter = pageSize; ReadSpec spec = new ReadSpec(s._counter, symbol, skipFirst, stopAfter, false); RCCube result = s._blackboard.Read(spec, s._counter, true, s._blackboard.Count); runner.Yield(closure, result); } }
public void EvalPeek(RCRunner runner, RCClosure closure, RCSymbol left, RCLong right) { int limit = (int)right[0]; lock (_readWriteLock) { Section s = GetSection(left); ReadSpec spec = s._counter.GetReadSpec(left, limit, false, true); Satisfy canSatisfy = s._counter.CanSatisfy(spec); RCCube result = s._blackboard.Read(spec, s._counter, true, s._blackboard.Count); if ((spec.SymbolUnlimited && result.Count > 0) || (!spec.SymbolUnlimited && result.Count >= left.Count * Math.Abs(spec.SymbolLimit))) { // If dispatch would yield, return lines. if (canSatisfy != Satisfy.Yes) { throw new Exception(); } runner.Yield(closure, RCBoolean.True); } else { if (canSatisfy != Satisfy.No) { throw new Exception(); } runner.Yield(closure, RCBoolean.False); } } }
public void EvalSelect(RCRunner runner, RCClosure closure, RCSymbol left, RCCube right) { RCLong args = new RCLong(0, 0); ReadCounter counter = new ReadCounter(right); ReadSpec spec = new ReadSpec(counter, left, args, 0, false, false, true, false); RCCube result = right.Read(spec, counter, true, right.Count); runner.Yield(closure, result); }
public void Read(RCRunner runner, RCClosure closure, RCSymbol symbol, ReadSpec spec) { lock (_readWriteLock) { // Make abstract symbols concrete Section section = GetSection(symbol); Satisfy canSatisfy = section._counter.CanSatisfy(spec); RCCube result = section._blackboard.Read(spec, section._counter, true, section._blackboard.Count); if (spec.SymbolUnlimited) { if (result.Count > 0) { // Notice the canSatisfy constraints here are less strict. // If the start point is greater than zero then we have to // do the full read and then just see if there were enough // rows to satisfy the constraints. if (canSatisfy == Satisfy.No) { throw new Exception(); } runner.Yield(closure, result); } else { if (canSatisfy == Satisfy.Yes) { throw new Exception(); } section._readWaiters.Enqueue(symbol, closure); } } else { if (result.Count >= symbol.Count * Math.Abs(spec.SymbolLimit)) { if (canSatisfy == Satisfy.No) { throw new Exception(); } runner.Yield(closure, result); } else { if (canSatisfy == Satisfy.Yes) { throw new Exception(); } section._readWaiters.Enqueue(symbol, closure); } } } }
public void EvalPoll(RCRunner runner, RCClosure closure, RCSymbol symbol, RCLong starts) { // Poll is like read but it will never block. lock (_readWriteLock) { Section s = GetSection(symbol); ReadSpec spec = s._counter.GetReadSpec(symbol, starts, false, true); RCCube result = s._blackboard.Read(spec, s._counter, true, s._blackboard.Count); runner.Yield(closure, result); } }
public void EvalSnap(RCRunner runner, RCClosure closure, RCSymbol left, RCLong right) { // With snap, the read instructions apply to each symbol in a family of symbols. // Not only to the symbol explcitly noted in the left argument. lock (_readWriteLock) { Section s = GetSection(left); // This line with the ConcreteSymbols should be added to other operators // RCSymbol concretes = s._counter.ConcreteSymbols (left, false); ReadSpec spec = new ReadSpec(s._counter, left, right, -1, false, false, true, false); // RCCube result = s._blackboard.Read (spec, s._counter, true, // s._blackboard.Count); RCCube result = s._blackboard.Read(spec, s._counter, true, s._blackboard.Count); runner.Yield(closure, result); } }
public void EvalThrottle(RCRunner runner, RCClosure closure, RCSymbol symbol, RCLong right) { int limit = (int)right[0]; lock (_readWriteLock) { Section s = GetSection(symbol); ReadSpec spec = s._counter.GetReadSpec(symbol, limit, false, true); Satisfy canSatisfy = s._counter.CanSatisfy(spec); RCCube result = s._blackboard.Read(spec, s._counter, true, s._blackboard.Count); if ((spec.SymbolUnlimited && result.Count > 0) || (!spec.SymbolUnlimited && result.Count >= symbol.Count * Math.Abs(spec.SymbolLimit))) { // If dispatch would yield, suspend. if (canSatisfy != Satisfy.Yes) { throw new Exception(); } s._throttleWaiters.Enqueue(symbol, closure); } else { // Return the count of the result set for now. // wny not just return the whole thing? // Because I want to write a version of this that can // know, in near constant time whether dispatch would yield, // without actually producing a result set. // That method can be used by dispatch, peek, and throttle. // So keep the interface locked down. if (canSatisfy != Satisfy.No) { throw new Exception(); } runner.Yield(closure, new RCLong(result.Lines)); } } }
public void EvalDispatch(RCRunner runner, RCClosure closure, RCSymbol symbol, RCLong right) { int limit = (int)right[0]; lock (_readWriteLock) { Section s = GetSection(symbol); ReadSpec spec = s._counter.GetReadSpec(symbol, limit, false, true); Satisfy canSatisfy = s._counter.CanSatisfy(spec); RCCube result = s._blackboard.Read(spec, s._counter, true, s._blackboard.Count); if ((spec.SymbolUnlimited && result.Count > 0) || (!spec.SymbolUnlimited && result.Count >= symbol.Count * Math.Abs(spec.SymbolLimit))) { if (canSatisfy != Satisfy.Yes) { throw new Exception(); } s._counter.Dispatch(s._blackboard, result.AcceptedLines); runner.Yield(closure, result); Dictionary <long, RCClosure> throttlers = null; s._throttleWaiters.GetReadersForSymbol(ref throttlers, result.AcceptedSymbols); ContinueWaiters(runner, throttlers); } else { if (canSatisfy != Satisfy.No) { throw new Exception(); } s._dispatchWaiters.Enqueue(symbol, closure); } } }