/// <summary> /// Atomically updates the field of the given object managed by this /// updater with the results of applying the given function to the /// current and given values, returning the updated value. The /// function should be side-effect-free, since it may be re-applied /// when attempted updates fail due to contention among threads. The /// function is applied with the current value as its first argument, /// and the given update as the second argument. /// </summary> /// <param name="obj"> An object whose field to get and set </param> /// <param name="x"> the update value </param> /// <param name="accumulatorFunction"> a side-effect-free function of two arguments </param> /// <returns> the updated value /// @since 1.8 </returns> public V AccumulateAndGet(T obj, V x, BinaryOperator <V> accumulatorFunction) { V prev, next; do { prev = Get(obj); next = accumulatorFunction.Apply(prev, x); } while (!CompareAndSet(obj, prev, next)); return(next); }
/// <summary> /// Atomically updates the current value with the results of /// applying the given function to the current and given values, /// returning the previous value. The function should be /// side-effect-free, since it may be re-applied when attempted /// updates fail due to contention among threads. The function /// is applied with the current value as its first argument, /// and the given update as the second argument. /// </summary> /// <param name="x"> the update value </param> /// <param name="accumulatorFunction"> a side-effect-free function of two arguments </param> /// <returns> the previous value /// @since 1.8 </returns> public V GetAndAccumulate(V x, BinaryOperator <V> accumulatorFunction) { V prev, next; do { prev = Get(); next = accumulatorFunction.Apply(prev, x); } while (!CompareAndSet(prev, next)); return(prev); }
/// <summary> /// Atomically updates the element at index {@code i} with the /// results of applying the given function to the current and /// given values, returning the updated value. The function should /// be side-effect-free, since it may be re-applied when attempted /// updates fail due to contention among threads. The function is /// applied with the current value at index {@code i} as its first /// argument, and the given update as the second argument. /// </summary> /// <param name="i"> the index </param> /// <param name="x"> the update value </param> /// <param name="accumulatorFunction"> a side-effect-free function of two arguments </param> /// <returns> the updated value /// @since 1.8 </returns> public E AccumulateAndGet(int i, E x, BinaryOperator <E> accumulatorFunction) { long offset = CheckedByteOffset(i); E prev, next; do { prev = GetRaw(offset); next = accumulatorFunction.Apply(prev, x); } while (!CompareAndSetRaw(offset, prev, next)); return(next); }
private static IElementValue EvaluateExpression(IList <Element> data, IObjectResolver dc) { if (data.Count == 0) { return(null); } Stack <IElementValue> output = new Stack <IElementValue>(); for (int j = 0; j < data.Count; j++) { Element element = data[j]; switch (element.Type) { case TokenType.BinaryOperator: ElementBinaryOperator binaryElement = (ElementBinaryOperator)element; BinaryOperator binaryOperator = (BinaryOperator)binaryElement.Operator; IElementValue b2 = output.Pop(); IElementValue b1 = output.Pop(); IElementValue binaryOutput = binaryOperator.Apply(b1, b2); output.Push(binaryOutput); break; case TokenType.UnitaryOperator: ElementUnitaryOperator unitaryElement = (ElementUnitaryOperator)element; UnitaryOperator unitaryOperator = (UnitaryOperator)unitaryElement.Operator; IElementValue u1 = output.Pop(); IElementValue unitaryOutput = unitaryOperator.Apply(u1); output.Push(unitaryOutput); break; case TokenType.Function: ElementFunction functionElement = (ElementFunction)element; FunctionOperator functionOperator = (FunctionOperator)functionElement.Operator; IElementValue[] paramVals = new IElementValue[functionElement.Parameters.Count]; for (int paramIndex = 0; paramIndex < functionElement.Parameters.Count; paramIndex++) { paramVals[paramIndex] = EvaluateExpression(functionElement.Parameters[paramIndex], dc); } IElementValue functionOutput = functionOperator.Apply(paramVals); output.Push(functionOutput); break; case TokenType.DecimalLiteral: case TokenType.IntegerLiteral: case TokenType.StringLiteral: case TokenType.BooleanLiteral: case TokenType.Selector: output.Push((IElementValue)element); break; case TokenType.OpenParenthesis: int parenthesis = 1; IList <Element> parenthesisElements = new List <Element>(); for (j = j + 1; j < data.Count; j++) { Element parenthesisElement = data[j]; if (parenthesisElement.Type == TokenType.OpenParenthesis) { parenthesis++; } else if (parenthesisElement.Type == TokenType.CloseParenthesis) { parenthesis--; if (parenthesis == 0) { IElementValue parenthesisOutput = EvaluateExpression(parenthesisElements, dc); output.Push(parenthesisOutput); break; } } else { parenthesisElements.Add(parenthesisElement); } } break; case TokenType.TernaryIf: IElementValue ternaryIfValue = output.Pop(); if (ternaryIfValue.Type != TokenType.BooleanLiteral) { throw new ELException("Condition is not boolean."); } bool condition = (bool)ternaryIfValue.Value; IList <Element> ternaryElements = new List <Element>(); bool elseReached = false; for (j = j + 1; j < data.Count; j++) { Element conditionValue = data[j]; if (conditionValue.Type == TokenType.TernaryElse) { elseReached = true; } if (condition == true) { if (elseReached == true) { j = data.Count; break; } ternaryElements.Add(conditionValue); } else { if (elseReached == true) { ternaryElements.Add(conditionValue); } } } IElementValue ternaryOutput = EvaluateExpression(ternaryElements, dc); output.Push(ternaryOutput); break; case TokenType.Variable: StringBuilder variableStr = new StringBuilder(); string expression; expression = ((ElementVariable)element).Expression; variableStr.Append(expression); bool variableBoundryHit = false; bool end = false; while (j + 1 < data.Count && end == false) { switch (data[j + 1].Type) { case TokenType.Variable: if (!variableBoundryHit) { end = true; break; } j++; variableStr.Append(((ElementVariable)data[j]).Expression); variableBoundryHit = false; break; case TokenType.OpenBracket: j++; int brackets = 1; variableBoundryHit = true; IList <Element> bracketElements = new List <Element>(); for (j = j + 1; j < data.Count; j++) { Element bracketElement = data[j]; if (bracketElement.Type == TokenType.OpenBracket) { brackets++; } else if (bracketElement.Type == TokenType.CloseBracket) { brackets--; if (brackets == 0) { IElementValue bracketOutput = EvaluateExpression(bracketElements, dc); if (bracketOutput.Type != TokenType.IntegerLiteral && bracketOutput.Type != TokenType.Selector) { throw new ELException("Integers and Selectors can only be used as brackets indexes."); } variableStr.Append("[").Append(bracketOutput.Value).Append("]"); break; } } else { bracketElements.Add(bracketElement); } } break; case TokenType.Dot: j++; variableBoundryHit = true; variableStr.Append("."); break; default: end = true; break; } } object value = dc.GetVariableObject(variableStr.ToString()); IElementValue elementValue; if (value is string) { elementValue = new ElementLiteral(TokenType.StringLiteral, value); } else if (value is bool) { elementValue = new ElementLiteral(TokenType.BooleanLiteral, value); } else if (value is int) { elementValue = new ElementLiteral(TokenType.IntegerLiteral, value); } else if (value is double || value is float || value is decimal) { elementValue = new ElementLiteral(TokenType.DecimalLiteral, Convert.ToDouble(value)); } else { elementValue = new ElementLiteral(TokenType.Object, value); } output.Push(elementValue); break; } } if (output.Count != 1) { throw new ELException("Error evaluating expression"); } return((IElementValue)output.Pop()); }