示例#1
0
        /// <summary>
        /// Post a commute on a ref in this transaction.
        /// </summary>
        /// <param name="r">The ref.</param>
        /// <param name="fn">The commuting function.</param>
        /// <param name="args">Additional arguments to the function.</param>
        /// <returns>The computed value.</returns>
        internal object DoCommute(Ref r, IFn fn, ISeq args)
        {
            if (!_info.IsRunning)
            {
                throw _retryex;
            }
            if (!_vals.ContainsKey(r))
            {
                object val = null;
                try
                {
                    r.EnterReadLock();
                    val = r.TryGetVal();
                }
                finally
                {
                    r.ExitReadLock();
                }
                _vals[r] = val;
            }
            List <CFn> fns;

            if (!_commutes.TryGetValue(r, out fns))
            {
                _commutes[r] = fns = new List <CFn>();
            }
            fns.Add(new CFn(fn, args));
            object ret = fn.applyTo(RT.cons(_vals[r], args));

            _vals[r] = ret;

            return(ret);
        }
示例#2
0
 static ISeq push(Node t, ISeq stack, bool asc)
 {
     while (t != null)
     {
         stack = RT.cons(t, stack);
         t     = asc ? t.Left : t.Right;
     }
     return(stack);
 }
示例#3
0
文件: Var.cs 项目: ryrency/Misc
        public object alterRoot(IFn fn, ISeq args)
        {
            object newRoot = fn.applyTo(RT.cons(_root, args));

            Validate(getValidator(), newRoot);
            object oldroot = getRoot();

            _root = newRoot;
            notifyWatches(oldroot, newRoot);
            return(newRoot);
        }
示例#4
0
            /// <summary>
            /// Worker method to execute the action on a thread.
            /// </summary>
            /// <param name="state">(not used)</param>
            /// <remarks>corresponds to doRun in Java version</remarks>
            void ExecuteAction(object state)
            {
                try
                {
                    Var.pushThreadBindings(RT.map(RT.AGENT, _agent));
                    Agent.Nested = PersistentVector.EMPTY;

                    bool hadError = false;

                    try
                    {
                        object oldval = _agent.State;
                        object newval = _fn.applyTo(RT.cons(_agent.State, _args));
                        _agent.SetState(newval);
                        _agent.notifyWatches(oldval, newval);
                    }
                    catch (Exception e)
                    {
                        // TODO: report/callback  (Java TODO)
                        _agent.AddError(e);
                        hadError = true;
                    }

                    if (!hadError)
                    {
                        releasePendingSends();
                    }

                    bool             popped = false;
                    IPersistentStack next   = null;
                    while (!popped)
                    {
                        IPersistentStack prior = _agent._q.Get();
                        next   = prior.pop();
                        popped = _agent._q.CompareAndSet(prior, next);
                    }

                    if (next.count() > 0)
                    {
                        ((Action)next.peek()).execute();
                    }
                }
                finally
                {
                    Nested = null;
                    Var.popThreadBindings();
                }
            }
示例#5
0
 /// <summary>
 /// Returns an <see cref="ISeq">ISeq</see> to iterate through the collection in the designated direction starting from a particular key.
 /// </summary>
 /// <param name="key">The key at which to start the iteration.</param>
 /// <param name="ascending">A flag indicating if the iteration is ascending or descending.</param>
 /// <returns>A sequence for first/rest iteration.</returns>
 /// <remarks>The key need not be in the collection.  If not present, the iteration will start with
 /// the first element with a key greater than (if asscending) or less than (if descending) the given key.</remarks>
 public ISeq seqFrom(object key, bool ascending)
 {
     if (_count > 0)
     {
         ISeq stack = null;
         Node t     = _tree;
         while (t != null)
         {
             int c = DoCompare(key, t.Key);
             if (c == 0)
             {
                 stack = RT.cons(t, stack);
                 return(new Seq(stack, ascending));
             }
             else if (ascending)
             {
                 if (c < 0)
                 {
                     stack = RT.cons(t, stack);
                     t     = t.Left;
                 }
                 else
                 {
                     t = t.Right;
                 }
             }
             else
             {
                 if (c > 0)
                 {
                     stack = RT.cons(t, stack);
                     t     = t.Right;
                 }
                 else
                 {
                     t = t.Left;
                 }
             }
         }
         if (stack != null)
         {
             return(new Seq(stack, ascending));
         }
     }
     return(null);
 }
示例#6
0
 public void step(LazyTransformer lt)
 {
     while (lt._stepper != null && MoveNext())
     {
         if (RT.isReduced(_xform.applyTo(RT.cons(lt, Current()))))
         {
             if (lt._rest != null)
             {
                 lt._rest._stepper = null;
             }
             break;
         }
     }
     if (lt._stepper != null)
     {
         _xform.invoke(lt);
     }
 }
        private bool Step()
        {
            _next = NONE;

            while (_next == NONE)
            {
                if (_buffer.IsEmpty())
                {
                    if (_completed)
                    {
                        return(false);
                    }
                    else if (_sourceEnum.MoveNext())
                    {
                        object iter;
                        if (_multi)
                        {
                            iter = _xf.applyTo(RT.cons(null, _sourceEnum.Current));
                        }
                        else
                        {
                            iter = _xf.invoke(null, _sourceEnum.Current);
                        }

                        if (RT.isReduced(iter))
                        {
                            _xf.invoke(null);
                            _completed = true;
                        }
                    }
                    else
                    {
                        _xf.invoke(null);
                        _completed = true;
                    }
                }
                else
                {
                    _next = _buffer.Remove();
                }
            }
            return(true);
        }
示例#8
0
 public void step(LazyTransformer lt)
 {
     while (lt._stepper != null && MoveNext())
     {
         if (RT.isReduced(_xform.applyTo(RT.cons(lt, Current()))))
         {
             lt._stepper = null;
             LazyTransformer et = lt;
             while (et._rest != null)
             {
                 et          = et._rest;
                 et._stepper = null;
             }
             _xform.invoke(et);
             return;
         }
     }
     if (lt._stepper != null)
     {
         _xform.invoke(lt);
     }
 }
示例#9
0
        /// <summary>
        /// Start a transaction and invoke a function.
        /// </summary>
        /// <param name="fn">The function to invoke.</param>
        /// <returns>The value computed by the function.</returns>
        object Run(IFn fn)
        {
            // TODO: Define an overload called on ThreadStartDelegate or something equivalent.

            bool          done   = false;
            object        ret    = null;
            List <Ref>    locked = new List <Ref>();
            List <Notify> notify = new List <Notify>();

            for (int i = 0; !done && i < RetryLimit; i++)
            {
                try
                {
                    GetReadPoint();
                    if (i == 0)
                    {
                        _startPoint = _readPoint;
                        _startTime  = Environment.TickCount;
                    }

                    _info = new Info(RUNNING, _startPoint);
                    ret   = fn.invoke();

                    // make sure no one has killed us before this point,
                    // and can't from now on
                    if (_info.Status.compareAndSet(RUNNING, COMMITTING))
                    {
                        foreach (KeyValuePair <Ref, List <CFn> > pair in _commutes)
                        {
                            Ref r = pair.Key;
                            if (_sets.Contains(r))
                            {
                                continue;
                            }

                            bool wasEnsured = _ensures.Contains(r);
                            // can't upgrade read lock, so release
                            ReleaseIfEnsured(r);
                            TryWriteLock(r);
                            locked.Add(r);

                            if (wasEnsured && r.CurrentValPoint() > _readPoint)
                            {
                                throw _retryex;
                            }

                            Info refinfo = r.TInfo;
                            if (refinfo != null && refinfo != _info && refinfo.IsRunning)
                            {
                                if (!Barge(refinfo))
                                {
                                    throw _retryex;
                                }
                            }
                            object val = r.TryGetVal();
                            _vals[r] = val;
                            foreach (CFn f in pair.Value)
                            {
                                _vals[r] = f.Fn.applyTo(RT.cons(_vals[r], f.Args));
                            }
                        }
                        foreach (Ref r in _sets)
                        {
                            TryWriteLock(r);
                            locked.Add(r);
                        }
                        // validate and enqueue notifications
                        foreach (KeyValuePair <Ref, object> pair in _vals)
                        {
                            Ref r = pair.Key;
                            r.Validate(pair.Value);
                        }

                        // at this point, all values calced, all refs to be written locked
                        // no more client code to be called
                        int  msecs       = System.Environment.TickCount;
                        long commitPoint = GetCommitPoint();
                        foreach (KeyValuePair <Ref, object> pair in _vals)
                        {
                            Ref    r      = pair.Key;
                            object oldval = r.TryGetVal();
                            object newval = pair.Value;

                            r.SetValue(newval, commitPoint, msecs);
                            if (r.getWatches().count() > 0)
                            {
                                notify.Add(new Notify(r, oldval, newval));
                            }
                        }

                        done = true;
                        _info.Status.set(COMMITTED);
                    }
                }
                catch (RetryEx)
                {
                    // eat this so we retry rather than fall out
                }
                catch (Exception ex)
                {
                    if (ContainsNestedRetryEx(ex))
                    {
                        // Wrapped exception, eat it.
                    }
                    else
                    {
                        throw;
                    }
                }
                finally
                {
                    for (int k = locked.Count - 1; k >= 0; --k)
                    {
                        locked[k].ExitWriteLock();
                    }
                    locked.Clear();
                    foreach (Ref r in _ensures)
                    {
                        r.ExitReadLock();
                    }
                    _ensures.Clear();
                    Stop(done ? COMMITTED : RETRY);
                    try
                    {
                        if (done) // re-dispatch out of transaction
                        {
                            foreach (Notify n in notify)
                            {
                                n._ref.NotifyWatches(n._oldval, n._newval);
                            }
                            foreach (Agent.Action action in _actions)
                            {
                                Agent.DispatchAction(action);
                            }
                        }
                    }
                    finally
                    {
                        notify.Clear();
                        _actions.Clear();
                    }
                }
            }
            if (!done)
            {
                throw new InvalidOperationException("Transaction failed after reaching retry limit");
            }
            return(ret);
        }
示例#10
0
        public static Expr Parse(ParserContext pcon, ISeq form, string name)
        {
            ISeq origForm = form;

            FnExpr fn = new FnExpr(Compiler.TagOf(form));

            fn._src = form;

            if (((IMeta)form.first()).meta() != null)
            {
                fn._onceOnly = RT.booleanCast(RT.get(RT.meta(form.first()), KW_ONCE));
            }

            fn.ComputeNames(form, name);

            List <string> prims = new List <string>();

            //arglist might be preceded by symbol naming this fn
            if (RT.second(form) is Symbol)
            {
                Symbol nm = (Symbol)RT.second(form);
                fn._thisName = nm.Name;
                fn._isStatic = false; // RT.booleanCast(RT.get(nm.meta(), Compiler.STATIC_KEY));
                form         = RT.cons(Compiler.FnSym, RT.next(RT.next(form)));
            }

            // Normalize body
            //now (fn [args] body...) or (fn ([args] body...) ([args2] body2...) ...)
            //turn former into latter
            if (RT.second(form) is IPersistentVector)
            {
                form = RT.list(Compiler.FnSym, RT.next(form));
            }

            fn.SpanMap = (IPersistentMap)Compiler.SourceSpanVar.deref();

            GenContext newContext = null;

            GenContext context = Compiler.CompilerContextVar.deref() as GenContext ?? Compiler.EvalContext;

            newContext = context.WithNewDynInitHelper(fn.InternalName + "__dynInitHelper_" + RT.nextID().ToString());
            Var.pushThreadBindings(RT.map(Compiler.CompilerContextVar, newContext));


            try
            {
                try
                {
                    Var.pushThreadBindings(RT.mapUniqueKeys(
                                               Compiler.ConstantsVar, PersistentVector.EMPTY,
                                               Compiler.ConstantIdsVar, new IdentityHashMap(),
                                               Compiler.KeywordsVar, PersistentHashMap.EMPTY,
                                               Compiler.VarsVar, PersistentHashMap.EMPTY,
                                               Compiler.KeywordCallsitesVar, PersistentVector.EMPTY,
                                               Compiler.ProtocolCallsitesVar, PersistentVector.EMPTY,
                                               Compiler.VarCallsitesVar, Compiler.EmptyVarCallSites(),
                                               Compiler.NoRecurVar, null));
                    SortedDictionary <int, FnMethod> methods = new SortedDictionary <int, FnMethod>();
                    FnMethod variadicMethod = null;

                    for (ISeq s = RT.next(form); s != null; s = RT.next(s))
                    {
                        FnMethod f = FnMethod.Parse(fn, (ISeq)RT.first(s), fn._isStatic);
                        if (f.IsVariadic)
                        {
                            if (variadicMethod == null)
                            {
                                variadicMethod = f;
                            }
                            else
                            {
                                throw new ParseException("Can't have more than 1 variadic overload");
                            }
                        }
                        else if (!methods.ContainsKey(f.RequiredArity))
                        {
                            methods[f.RequiredArity] = f;
                        }
                        else
                        {
                            throw new ParseException("Can't have 2 overloads with the same arity.");
                        }
                        if (f.Prim != null)
                        {
                            prims.Add(f.Prim);
                        }
                    }

                    if (variadicMethod != null && methods.Count > 0 && methods.Keys.Max() >= variadicMethod.NumParams)
                    {
                        throw new ParseException("Can't have fixed arity methods with more params than the variadic method.");
                    }

                    if (fn._isStatic && fn.Closes.count() > 0)
                    {
                        throw new ParseException("static fns can't be closures");
                    }

                    IPersistentCollection allMethods = null;
                    foreach (FnMethod method in methods.Values)
                    {
                        allMethods = RT.conj(allMethods, method);
                    }
                    if (variadicMethod != null)
                    {
                        allMethods = RT.conj(allMethods, variadicMethod);
                    }

                    fn._methods          = allMethods;
                    fn._variadicMethod   = variadicMethod;
                    fn.Keywords          = (IPersistentMap)Compiler.KeywordsVar.deref();
                    fn.Vars              = (IPersistentMap)Compiler.VarsVar.deref();
                    fn.Constants         = (PersistentVector)Compiler.ConstantsVar.deref();
                    fn.KeywordCallsites  = (IPersistentVector)Compiler.KeywordCallsitesVar.deref();
                    fn.ProtocolCallsites = (IPersistentVector)Compiler.ProtocolCallsitesVar.deref();
                    fn.VarCallsites      = (IPersistentSet)Compiler.VarCallsitesVar.deref();

                    fn._constantsID = RT.nextID();
                }
                finally
                {
                    Var.popThreadBindings();
                }


                IPersistentMap fmeta = RT.meta(origForm);
                if (fmeta != null)
                {
                    fmeta = fmeta.without(RT.LineKey).without(RT.ColumnKey).without(RT.SourceSpanKey).without(RT.FileKey);
                }
                fn._hasMeta = RT.count(fmeta) > 0;


                IPersistentVector primTypes = PersistentVector.EMPTY;
                foreach (string typename in prims)
                {
                    primTypes = primTypes.cons(Type.GetType(typename));
                }

                fn.Compile(
                    fn.IsVariadic ? typeof(RestFn) : typeof(AFunction),
                    null,
                    primTypes,
                    fn._onceOnly,
                    newContext);

                if (fn.SupportsMeta)
                {
                    return(new MetaExpr(fn, MapExpr.Parse(pcon.EvalOrExpr(), fmeta)));
                }
                else
                {
                    return(fn);
                }
            }
            finally
            {
                if (newContext != null)
                {
                    Var.popThreadBindings();
                }
            }
        }
示例#11
0
            static object syntaxQuote(object form)
            {
                object ret;

                if (Compiler.isSpecial(form))
                {
                    ret = RT.list(Compiler.QUOTE, form);
                }
                else if (form is Symbol)
                {
                    Symbol sym = (Symbol)form;
                    if (sym.Namespace == null && sym.Name.EndsWith("#"))
                    {
                        IPersistentMap gmap = (IPersistentMap)GENSYM_ENV.deref();
                        if (gmap == null)
                        {
                            throw new InvalidDataException("Gensym literal not in syntax-quote");
                        }
                        Symbol gs = (Symbol)gmap.valAt(sym);
                        if (gs == null)
                        {
                            GENSYM_ENV.set(gmap.assoc(sym, gs = Symbol.intern(null,
                                                                              sym.Name.Substring(0, sym.Name.Length - 1)
                                                                              + "__" + RT.nextID() + "__auto__")));
                        }
                        sym = gs;
                    }
                    else if (sym.Namespace == null && sym.Name.EndsWith("."))
                    {
                        Symbol csym = Symbol.intern(null, sym.Name.Substring(0, sym.Name.Length - 1));
                        csym = Compiler.resolveSymbol(csym);
                        sym  = Symbol.intern(null, csym.Name + ".");
                    }
                    else if (sym.Namespace == null && sym.Name.StartsWith("."))
                    {
                        // simply quote method names
                    }
                    else
                    {
                        sym = Compiler.resolveSymbol(sym);
                    }
                    ret = RT.list(Compiler.QUOTE, sym);
                }
                //else if (form is Unquote)
                //    return ((Unquote)form).Obj;
                // Rev 1184
                else if (isUnquote(form))
                {
                    return(RT.second(form));
                }
                else if (isUnquoteSplicing(form))
                {
                    throw new ArgumentException("splice not in list");
                }
                else if (form is IPersistentCollection)
                {
                    if (form is IPersistentMap)
                    {
                        IPersistentVector keyvals = flattenMap(form);
                        ret = RT.list(APPLY, HASHMAP, RT.list(SEQ, RT.cons(CONCAT, sqExpandList(keyvals.seq()))));
                    }
                    else if (form is IPersistentVector)
                    {
                        ret = RT.list(APPLY, VECTOR, RT.list(SEQ, RT.cons(CONCAT, sqExpandList(((IPersistentVector)form).seq()))));
                    }
                    else if (form is IPersistentSet)
                    {
                        ret = RT.list(APPLY, HASHSET, RT.list(SEQ, RT.cons(CONCAT, sqExpandList(((IPersistentSet)form).seq()))));
                    }
                    else if (form is ISeq || form is IPersistentList)
                    {
                        ISeq seq = RT.seq(form);
                        if (seq == null)
                        {
                            ret = RT.cons(LIST, null);
                        }
                        else
                        {
                            ret = RT.list(SEQ, RT.cons(CONCAT, sqExpandList(seq)));
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("Unknown Collection type");
                    }
                }
                else if (form is Keyword ||
                         Util.IsNumeric(form) ||
                         form is Char ||
                         form is String)
                {
                    ret = form;
                }
                else
                {
                    ret = RT.list(Compiler.QUOTE, form);
                }

                if (form is IObj && RT.meta(form) != null)
                {
                    //filter line numbers
                    IPersistentMap newMeta = ((IObj)form).meta().without(RT.LINE_KEY);
                    if (newMeta.count() > 0)
                    {
                        return(RT.list(WITH_META, ret, syntaxQuote(((IObj)form).meta())));
                    }
                }
                return(ret);
            }
示例#12
0
        public object alter(IFn fn, ISeq args)
        {
            LockingTransaction t = LockingTransaction.GetEx();

            return(t.DoSet(this, fn.applyTo(RT.cons(t.DoGet(this), args))));
        }
示例#13
0
 /// <summary>
 /// Add an error.
 /// </summary>
 /// <param name="e">The exception to add.</param>
 public void AddError(Exception e)
 {
     _errors = RT.cons(e, _errors);
 }
示例#14
0
 public ISeq nodeSeq()
 {
     return((ISeq)RT.cons(this, null));
 }
示例#15
0
            void ExecuteAction(object state)
            {
                try
                {
                    Agent.Nested = PersistentVector.EMPTY;

                    Exception error = null;

                    try
                    {
                        object oldval = _agent.State;
                        object newval = _fn.applyTo(RT.cons(_agent.State, _args));
                        _agent.SetState(newval);
                        _agent.NotifyWatches(oldval, newval);
                    }
                    catch (Exception e)
                    {
                        error = e;
                    }

                    if (error == null)
                    {
                        releasePendingSends();
                    }
                    else
                    {
                        Nested = null;  // allow errorHandler to send
                        if (_agent._errorHandler != null)
                        {
                            try
                            {
                                _agent._errorHandler.invoke(_agent, error);
                            }
                            catch (Exception)
                            {
                                // ignore error handler errors
                            }
                        }
                        if (_agent._errorMode == ContinueKeyword)
                        {
                            error = null;
                        }
                    }

                    bool        popped = false;
                    ActionQueue next   = null;
                    while (!popped)
                    {
                        ActionQueue prior = _agent._aq.Get();
                        next   = new ActionQueue(prior._q.pop(), error);
                        popped = _agent._aq.CompareAndSet(prior, next);
                    }

                    if (error == null && next._q.count() > 0)
                    {
                        ((Action)next._q.peek()).execute();
                    }
                }
                finally
                {
                    Nested = null;
                }
            }
示例#16
0
 public object alter(IFn fn, ISeq args)
 {
     set(fn.applyTo(RT.cons(deref(), args)));
     return(this);
 }
示例#17
0
 public ISeq cons(object o)
 {
     return(RT.cons(o, seq()));
 }
示例#18
0
文件: FnExpr.cs 项目: ryrency/Misc
        public static Expr Parse(object frm, string name)
        {
            ISeq form = (ISeq)frm;

            FnExpr fn = new FnExpr(Compiler.TagOf(form));

            if (((IMeta)form.first()).meta() != null)
            {
                fn._onceOnly  = RT.booleanCast(RT.get(RT.meta(form.first()), KW_ONCE));
                fn._superName = (string)RT.get(RT.meta(form.first()), KW_SUPER_NAME);
            }


            fn.ComputeNames(form, name);

            try
            {
                Var.pushThreadBindings(RT.map(
                                           Compiler.CONSTANTS, PersistentVector.EMPTY,
                                           Compiler.KEYWORDS, PersistentHashMap.EMPTY,
                                           Compiler.VARS, PersistentHashMap.EMPTY));

                //arglist might be preceded by symbol naming this fn
                if (RT.second(form) is Symbol)
                {
                    fn._thisName = ((Symbol)RT.second(form)).Name;
                    form         = RT.cons(Compiler.FN, RT.next(RT.next(form)));
                }

                // Normalize body
                // If it is (fn [arg...] body ...), turn it into
                //          (fn ([arg...] body...))
                // so that we can treat uniformly as (fn ([arg...] body...) ([arg...] body...) ... )
                if (RT.second(form) is IPersistentVector)
                {
                    form = RT.list(Compiler.FN, RT.next(form));
                }


                FnMethod variadicMethod = null;
                SortedDictionary <int, FnMethod> methods = new SortedDictionary <int, FnMethod>();

                for (ISeq s = RT.next(form); s != null; s = RT.next(s))
                {
                    FnMethod f = FnMethod.Parse(fn, (ISeq)RT.first(s));
                    if (f.IsVariadic)
                    {
                        if (variadicMethod == null)
                        {
                            variadicMethod = f;
                        }
                        else
                        {
                            throw new Exception("Can't have more than 1 variadic overload");
                        }
                    }
                    else if (!methods.ContainsKey(f.RequiredArity))
                    {
                        methods[f.RequiredArity] = f;
                    }
                    else
                    {
                        throw new Exception("Can't have 2 overloads with the same arity.");
                    }
                }

                if (variadicMethod != null && methods.Count > 0 && methods.Keys.Max() >= variadicMethod.NumParams)
                {
                    throw new Exception("Can't have fixed arity methods with more params than the variadic method.");
                }

                IPersistentCollection allMethods = null;
                foreach (FnMethod method in methods.Values)
                {
                    allMethods = RT.conj(allMethods, method);
                }
                if (variadicMethod != null)
                {
                    allMethods = RT.conj(allMethods, variadicMethod);
                }

                fn._methods        = allMethods;
                fn._variadicMethod = variadicMethod;
                fn._keywords       = (IPersistentMap)Compiler.KEYWORDS.deref();
                fn._vars           = (IPersistentMap)Compiler.VARS.deref();
                fn._constants      = (PersistentVector)Compiler.CONSTANTS.deref();
                fn._constantsID    = RT.nextID();
            }
            finally
            {
                Var.popThreadBindings();
            }
            // JAVA: fn.compile();
            return(fn);
        }