Exemple #1
0
        private static void TryToTransitPersonToTargetSector(TransitionPoolItem transitionItem)
        {
            var nextSector = transitionItem.NextSector;

            var nodeForTransition = nextSector.Map.Transitions
                                    .First(x => x.Value.SectorNode.Sector == transitionItem.OldSector).Key;
            var availableNextNodesToTransition = nextSector.Map.GetNext(nodeForTransition);

            var allPotentialNodesToTransition = new[] { nodeForTransition }.Concat(availableNextNodesToTransition);
            var allAvailableNodesToTransition = allPotentialNodesToTransition
                                                .Where(x => FilterNodeToTransition(x, nextSector)).ToArray();

            var availableNodeToTransition = allAvailableNodesToTransition.FirstOrDefault();

            if (availableNodeToTransition is null)
            {
                // I dont know what I can do.
                // I think it was solved when a some transition pool was developed.
                // Now just return person into old sector in old transition node.
                nextSector = transitionItem.OldSector;
                availableNodeToTransition = transitionItem.OldNode;
            }

            var actorInNewSector =
                new Actor(transitionItem.Person, transitionItem.TaskSource, availableNodeToTransition);

            nextSector.ActorManager.Add(actorInNewSector);
        }
Exemple #2
0
        private async Task ProcessInnerAsync(IGlobe globe, ISector sector, IActor actor, SectorTransition transition)
        {
            var sectorNode = transition.SectorNode;

            //TODO Разобраться с этим кодом.
            // https://blog.cdemi.io/async-waiting-inside-c-sharp-locks/
            //Asynchronously wait to enter the Semaphore. If no-one has been granted access to the Semaphore, code execution will proceed, otherwise this thread waits here until the semaphore is released
#pragma warning disable CA2007 // Consider calling ConfigureAwait on the awaited task
            await _semaphoreSlim.WaitAsync();

#pragma warning restore CA2007 // Consider calling ConfigureAwait on the awaited task
            try
            {
                if (sectorNode.State != SectorNodeState.SectorMaterialized)
                {
                    await _globeExpander.ExpandAsync(sectorNode).ConfigureAwait(false);

                    globe.AddSectorNode(sectorNode);
                }

                // It was used as fallback later.
                var oldActorNode = actor.Node;

                try
                {
                    sector.ActorManager.Remove(actor);
                }
                catch (InvalidOperationException exception)
                {
                    // Пока ничего не делаем
                    Console.WriteLine(exception);
                    Console.WriteLine(sector.GetHashCode());
                    Console.WriteLine(actor);
                }

                var nextSector = sectorNode.Sector;

                var transitionItem =
                    new TransitionPoolItem(actor.Person, actor.TaskSource, nextSector, sector, oldActorNode);
                _transitionPool.Push(transitionItem);
            }
            finally
            {
                //When the task is ready, release the semaphore. It is vital to ALWAYS release the semaphore when we are ready, or else we will end up with a Semaphore that is forever locked.
                //This is why it is important to do the Release within a try...finally clause; program execution may crash or take a different path, this way you are guaranteed execution
                _semaphoreSlim.Release();
            }
        }
        private async Task ProcessInternalAsync(IGlobe globe, ISector sourceSector, IActor actor,
                                                SectorTransition transition)
        {
            var sectorNode = transition.SectorNode;

            await _semaphoreSlim.WaitAsync().ConfigureAwait(false);

            try
            {
                if (sectorNode.State != SectorNodeState.SectorMaterialized)
                {
                    await _globeExpander.ExpandAsync(sectorNode).ConfigureAwait(false);

                    globe.AddSectorNode(sectorNode);
                }

                // It was used as fallback later.
                var oldActorNode = actor.Node;

                sourceSector.ActorManager.Remove(actor);

                var targetSector = sectorNode.Sector;

                if (targetSector is null)
                {
                    throw new InvalidOperationException();
                }

                var transitionItem = new TransitionPoolItem(
                    actor.Person,
                    actor.TaskSource,
                    targetSector,
                    sourceSector,
                    oldActorNode);
                _transitionPool.Push(transitionItem);
            }
            finally
            {
                //When the task is ready, release the semaphore. It is vital to ALWAYS release the semaphore when we are ready, or else we will end up with a Semaphore that is forever locked.
                //This is why it is important to do the Release within a try...finally clause; program execution may crash or take a different path, this way you are guaranteed execution
                _semaphoreSlim.Release();
            }
        }
Exemple #4
0
        public void UpdateTransitions()
        {
            // The counter is restriction of transition per globe iteration.
            var counter = TransitionPerGlobeIteration;
            TransitionPoolItem transitionItem = null;

            // Transit persons from pool to target sector levels while the pool is not empty or transition limit reached.
            do
            {
                transitionItem = _transitionPool.Pop();

                if (transitionItem is null)
                {
                    return;
                }

                TryToTransitPersonToTargetSector(transitionItem);

                counter--;
            } while (counter > 0);
        }
 public void Push(TransitionPoolItem poolItem)
 {
     _queue.Enqueue(poolItem);
 }