/// <summary>
 /// Wait for writer to finish.
 /// </summary>
 /// <param name="me">caller's XState object</param>
 /// <param name="writer">prior writer's XState object</param>
 public void ResolveConflict(XState me, XState writer)
 {
     while (writer.State == XStates.ACTIVE)
     {
         writer.BlockWhileActiveAndNotWaiting();
     }
 }
Пример #2
0
        public static object Run(XStart start, params object[] args)
        {
            object result = null;

            depth++;
            // less confusing if higher number is higher priority
            long priority = Manager.Priority;

            while (!XAction.stop)
            {
                xState = new XState(priority);
                try
                {
                    result = start(args);                       // user's delegate
                    depth--;
                }
                catch (AbortedException e)                      // aborted by synch conflict, retry
                {
                    if (depth > 1)
                    {
                        depth--;
                        throw e;
                    }
                }
                catch (RetryException e)                                // user wants to retry
                {
                    if (depth > 1)
                    {
                        depth--;
                        throw e;
                    }
                    // block until another transctions writes something I've read (aborting me)
                    xState.BlockWhileActive();
                }
                depth--;
                if (depth > 0)
                {
                    return(result);
                }
                else
                {
                    if (xState.Commit())
                    {
                        XAction.myCommits++;
                        return(result);
                    }
                    else
                    {
                        XAction.myAborts++;
                    }
                }
            }
            UpdateStatistic(ref commits, myCommits);
            UpdateStatistic(ref aborts, myAborts);
            throw new GracefulException();
        }
Пример #3
0
 /// <summary>
 /// Either give the writer a chance to finish it, abort it, or both.
 /// </summary>
 /// <param name="me">caller's XState object</param>
 /// <param name="writer">prior writer's XState object</param>
 public void ResolveConflict(XState me, XState writer)
 {
     if (writer.priority > me.priority)
     {
         writer.BlockWhileActiveAndNotWaiting();                 // wait for same or higher priority
     }
     else
     {
         writer.Abort();                                         // abort lower priority
     }
 }
Пример #4
0
 bool ConflictsWithReader(XState me, ICollection readers)
 {
     foreach (XState reader in readers)
     {
         if (reader.State == XStates.ACTIVE && reader != me)
         {
             return(true);
         }
     }
     return(false);
 }
Пример #5
0
 /// <summary>
 /// If prior transaction is
 ///		active and higher priority, then wait.
 ///     active and lower priority, then abort it.
 ///		waiting and higher priority, then adopt its priority and abort it.
 ///     waiting and lower priority, then abort it.
 /// </summary>
 /// <param name="me">caller's XState object</param>
 /// <param name="writer">prior writer's XState object</param>
 public void ResolveConflict(XState me, XState writer)
 {
     if (writer.waiting || writer.priority < me.priority)
     {
         writer.Abort();
     }
     else
     {
         me.Waiting();                                           // announce that I'm waiting
         writer.BlockWhileActiveAndNotWaiting();                 // wait for prior transaction to become not ACTIVE
         me.NotWaiting();                                        // announce that I'm no longer waiting
     }
 }
        /// <summary>
        /// If exponential backoff fails, then abort the writer.
        /// </summary>
        /// <param name="me">caller's XState object</param>
        /// <param name="writer">prior writer's XState object</param>
        public void ResolveConflict(XState me, XState writer)
        {
            int sleep = random.Next(1 << attempts);

            Thread.Sleep(sleep);
            if (writer.State != XStates.ACTIVE)
            {
                attempts = 0;
            }
            else
            {
                writer.Abort();                         // no more Mister Nice Guy.
                if (attempts < MAX_LOG_BACKOFF)
                {
                    attempts++;
                }
            }
            return;
        }
Пример #7
0
 /// <summary>
 /// Principal constructor.
 /// </summary>
 public Locator()
 {
     this.writer    = XState.COMMITTED;
     this.newObject = null;
     this.oldObject = null;
 }
 /// <summary>
 /// Immediately abort the writer.
 /// </summary>
 /// <param name="me">caller's XState object</param>
 /// <param name="writer">prior writer's XState object</param>
 public void ResolveConflict(XState me, XState writer)
 {
     writer.Abort();
 }
Пример #9
0
        /// <summary>
        /// Open object with intention to modify.
        /// </summary>
        /// <returns>Private version of object</returns>
        public ICloneable OpenWrite()
        {
            XState  me         = XAction.XState;           // my transaction
            Locator oldLocator = (Locator)this.start;
            XState  writer     = oldLocator.writer;

            if (writer == me)
            {
                return(oldLocator.newObject);
            }

            IContentionManager manager = XAction.Manager;             // my manager

            // allocate successor
            Locator newLocator = new Locator();

            newLocator.writer = me;
            ICloneable oldVersion = null;
            ICloneable newVersion = null;

            while (true)
            {
retry:
                // read locator
                switch (writer.State)
                {
                case XStates.ACTIVE:
                    // abort or wait?
                    manager.ResolveConflict(me, writer);
                    goto retry;                                                 // try again

                case XStates.COMMITTED:
                    oldVersion = newLocator.oldObject = oldLocator.newObject;
                    break;

                case XStates.ABORTED:
                    oldVersion = newLocator.oldObject = oldLocator.oldObject;
                    break;

                default:
                    throw new PanicException("Unexpected transaction state: {0}", writer.State);
                }
                switch (me.State)
                {
                case XStates.ABORTED:
                    throw new AbortedException();

                case XStates.COMMITTED:
                    return(oldVersion);

                case XStates.ACTIVE:
                    // check for read conflicts
                    bool readConflict = false;
                    foreach (XState reader in oldLocator)
                    {
                        if (reader.State == XStates.ACTIVE && reader != me)
                        {
                            manager.ResolveConflict(me, reader);
                            readConflict = true;
                        }
                        if (readConflict)
                        {
                            goto retry;
                        }
                    }
                    // no conflict
                    newVersion = newLocator.newObject = (ICloneable)oldVersion.Clone();
                    // try to install
                    if ((Locator)(Interlocked.CompareExchange(
                                      ref start,
                                      newLocator,
                                      oldLocator)) == oldLocator)
                    {
                        return(newVersion);
                    }
                    break;

                default:
                    throw new PanicException("Unknown transaction state: {0}", me.State);
                }
                oldLocator = (Locator)this.start;
                writer     = oldLocator.writer;
            }
        }
Пример #10
0
        /// <summary>
        /// Open object with intention to read.
        /// </summary>
        /// <returns>Shared version of object</returns>
        public ICloneable OpenRead()
        {
            XState  me         = XAction.XState;     // my transaction
            Locator oldLocator = (Locator)this.start;
            XState  writer     = oldLocator.writer;

            if (writer == me)
            {
                return(oldLocator.newObject);
            }
            foreach (XState reader in oldLocator)
            {
                if (reader == me)
                {
                    return(oldLocator.newObject);
                }
            }
            IContentionManager manager = XAction.Manager;             // my manager

            // allocate successor
            Locator newLocator = new Locator();

            newLocator.writer = XState.COMMITTED;
            while (true)
            {
retry:
                // read locator
                ICloneable version = null;
                switch (writer.State)
                {
                case XStates.ACTIVE:
                    // abort or wait?
                    manager.ResolveConflict(me, writer);
                    goto retry;                                                 // try again

                case XStates.COMMITTED:
                    version = oldLocator.newObject;
                    break;

                case XStates.ABORTED:
                    version = oldLocator.oldObject;
                    break;

                default:
                    throw new PanicException("Unknown transaction state: {0}", writer.State);
                }
                switch (me.State)
                {
                case XStates.ABORTED:
                    throw new AbortedException();

                case XStates.COMMITTED:
                    return(version);

                case XStates.ACTIVE:
                    newLocator.newObject = version;
                    newLocator.reader    = me;
                    if (oldLocator.reader != null)
                    {
                        newLocator.prevReader = oldLocator;
                    }
                    else
                    {
                        newLocator.prevReader = null;
                    }
                    if (Interlocked.CompareExchange(
                            ref start,
                            newLocator,
                            oldLocator) == oldLocator)
                    {
                        return(version);
                    }
                    break;

                default:
                    throw new PanicException("Unknown transaction state: {0}", me.State);
                }
                oldLocator = (Locator)this.start;
                writer     = oldLocator.writer;
            }
        }
Пример #11
0
 /// <summary>
 /// Initialize XStatus constant.
 /// </summary>
 /// <param name="init">must be one of static state objects</param>
 private XStatus(XState init)
 {
     state = (int)init;
     // convenient to assign highest priority to constants
     priority = Int64.MaxValue;
 }