Пример #1
0
        public static void Main2()
        {
            var totalTasks = 100000;
            var tasks      = new TaskSlim <bool> [totalTasks];

            // Initialization
            Action continuation = () =>
            {
                // no-op
            };

            for (int i = 0; i < totalTasks; i++)
            {
                tasks[i] = new TaskSlim <bool>(recycler: null);
                tasks[i].SetContinuation(continuation);
            }

            var res = Parallel.ForEach(tasks, task =>
            {
                try
                {
                    task.TrySetResult(true, runContinuationAsync: false);
                }
                catch (Exception e)
                {
                    Console.Error.WriteLine("Error  " + e);
                }
            });

            Console.WriteLine("All done");
        }
Пример #2
0
        internal TaskSlim __BasicPublishTask(string exchange, string routingKey, bool mandatory, bool immediate,
                                             BasicProperties properties, ArraySegment <byte> buffer)
        {
            if (properties == null)
            {
                properties = BasicProperties.Empty;
            }

            TaskSlim tcs  = _taskLightPool.GetObject();
            var      args = _basicPubArgsPool.GetObject();

            args.exchange   = exchange;
            args.immediate  = immediate;
            args.routingKey = routingKey;
            args.mandatory  = mandatory;
            args.properties = properties;
            args.buffer     = buffer;

            _connectionIo.SendCommand(_channelNum, 60, 40,
                                      null, // AmqpChannelLevelFrameWriter.InternalBasicPublish,
                                      reply: (channel, classMethodId, error) =>
            {
                if (properties.IsReusable)
                {
                    _channel.Return(properties);                             // the tcs is left for the confirmation keeper
                }
                tcs.SetCompleted();
                return(Task.CompletedTask);
            },
                                      expectsReply: false,
                                      tcsL: null,
                                      optArg: args);

            return(tcs);
        }
        public void SetException_Should_RunContinuationIfOneIsPresent()
        {
            var taskSlim = new TaskSlim(null);

            taskSlim.IsCompleted.Should().BeFalse();
            taskSlim.HasContinuation.Should().BeFalse();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();

            var runCont = false;

            taskSlim.OnCompleted(() =>
            {
                runCont = true;

                Assert.Throws <Exception>(() =>
                {
                    taskSlim.GetResult();                     // throws the exception
                });
            });

            taskSlim.SetException(new Exception("nope"), runContinuationAsync: false);

            runCont.Should().BeTrue();
        }
Пример #4
0
		public void Add(TaskSlim tcs)
		{
			// happens past semaphore, from the frame writing thread, thus "safe"

			var success = false;

			// for (int i = 0; i < _tasks.Length; i++)
			{
				var id = GetNext();
				var index = id % _max;

				if (Interlocked.CompareExchange(ref _tasks[index], tcs, null) == null)
				{
					success = true;
//					break;
				}
				else
				{
					// Spot in use, so continue up to sizeOf(_tasks) attempts
				}
			}

			if (!success) // probably will never happen due to the semaphore, but just in case. 
			{
				// fail fast, better than leaving the task hanging forever
				tcs.SetException(new Exception("MessagesPendingConfirmationKeeper: Could not find free spot for the waiting task"));
			}
		}
        public void Add(TaskSlim tcs)
        {
            // happens past semaphore, from the frame writing thread, thus "safe"

            var id = GetNext();
            var index = id % _max;
            _tasks[index] = tcs;
        }
        public void Add(TaskSlim tcs)
        {
            // happens past semaphore, from the frame writing thread, thus "safe"

            var id    = GetNext();
            var index = id % _max;

            _tasks[index] = tcs;
        }
Пример #7
0
 public void Dispose()
 {
     Channel          = ClassId = MethodId = 0;
     commandGenerator = null;
     ReplyAction      = null;
     ExpectsReply     = false;
     OptionalArg      = null;
     PrepareAction    = null;
     Tcs     = null;
     TcsSlim = null;
 }
Пример #8
0
 private void SetErrorResultIfErrorPending(bool expectsReply, Func <ushort, int, AmqpError, Task> replyFn,
                                           TaskCompletionSource <bool> tcs, TaskSlim taskSlim)
 {
     if (expectsReply)
     {
         replyFn(0, 0, _lastError);
     }
     else
     {
         AmqpIOBase.SetException(tcs, _lastError, 0);
         AmqpIOBase.SetException(taskSlim, _lastError, 0);
     }
 }
        public void SetCompleted_Should_setCompletedFlags2()
        {
            var taskSlim = new TaskSlim(null);

            taskSlim.IsCompleted.Should().BeFalse();
            taskSlim.HasContinuation.Should().BeFalse();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();

            taskSlim.SetCompleted(runContinuationAsync: true);

            taskSlim.IsCompleted.Should().BeTrue();
            taskSlim.HasContinuation.Should().BeFalse();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeTrue();
        }
Пример #10
0
        public void Dispose()
        {
            Channel          = ClassId = MethodId = 0;
            commandGenerator = null;
            ReplyAction      = null;
            ExpectsReply     = false;
            OptionalArg      = null;
            PrepareAction    = null;
            Tcs                = null;
            TcsSlim            = null;
            _whenReplyReceived = null;

            if (Interlocked.CompareExchange(ref _inUse, value: 0, comparand: 1) != 1)
            {
                throw new Exception("CommandToSend being shared inadvertently 1");
            }
        }
Пример #11
0
        public void MultiThreaded_TrySetComplete(bool isSetCompleteTest, int howManyThreads)
        {
            int continuationCalledCounter = 0;
            int completedGainedCounter    = 0;
            int completedLossedCounter    = 0;

            var taskSlim = new TaskSlim(null);

            taskSlim.SetContinuation(() =>
            {
                Interlocked.Increment(ref continuationCalledCounter);
            });

            var @syncEvent = new ManualResetEventSlim(false);

            for (int i = 0; i < howManyThreads; i++)
            {
                ThreadFactory.BackgroundThread((index) =>
                {
                    @syncEvent.Wait();

                    var result = isSetCompleteTest ?
                                 taskSlim.TrySetCompleted() :
                                 taskSlim.TrySetException(new Exception("bah"));

                    if (result)
                    {
                        Interlocked.Increment(ref completedGainedCounter);
                    }
                    else
                    {
                        Interlocked.Increment(ref completedLossedCounter);
                    }
                }, "T_" + i, i);
            }

            Thread.Sleep(0);

            @syncEvent.Set();

            Thread.Sleep(1000);

            continuationCalledCounter.Should().Be(1, "continuation cannot be called more than once");
            completedGainedCounter.Should().Be(1, "only 1 thread could have taken the lock successfully");
            completedLossedCounter.Should().Be(howManyThreads - 1, "all other threads should have been unsuccessful");
        }
Пример #12
0
        public void OnCompleted_Should_SetHasContinuationFlag()
        {
            var taskSlim = new TaskSlim(null);

            taskSlim.IsCompleted.Should().BeFalse();
            taskSlim.HasContinuation.Should().BeFalse();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();

            taskSlim.OnCompleted(() =>
            {
            });

            taskSlim.IsCompleted.Should().BeFalse();
            taskSlim.HasContinuation.Should().BeTrue();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();
        }
Пример #13
0
        public void OnCompleted_Should_SetHasContinuationFlag()
        {
            var taskSlim = new TaskSlim(null);

            taskSlim.IsCompleted.Should().BeFalse();
            taskSlim.HasContinuation.Should().BeFalse();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();

            taskSlim.OnCompleted(() =>
            {
            });

            taskSlim.IsCompleted.Should().BeFalse();
            taskSlim.HasContinuation.Should().BeTrue();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();
        }
Пример #14
0
		public RpcHelper(Channel channel, int maxConcurrentCalls, ConsumeMode mode, int timeoutInMs = 6000)
		{
			if (maxConcurrentCalls <= 0) throw new ArgumentOutOfRangeException("maxConcurrentCalls");

			_channel = channel;
			_maxConcurrentCalls = maxConcurrentCalls;
			_mode = mode;
			_timeoutInMs = timeoutInMs;
			_timeoutInTicks = timeoutInMs * TimeSpan.TicksPerMillisecond;

			_semaphoreSlim = new SemaphoreSlim(maxConcurrentCalls, maxConcurrentCalls);

			// the impl keeps a timer pool so this is light and efficient
			// _timeoutTimer = new System.Threading.Timer(OnTimeoutCheck, null, timeoutInMs, timeoutInMs);

			_pendingCalls = new TaskSlim<MessageDelivery>[maxConcurrentCalls];
			_taskResultPool = new ObjectPool<TaskSlim<MessageDelivery>>(() =>
				new TaskSlim<MessageDelivery>((inst) => _taskResultPool.PutObject(inst)), maxConcurrentCalls, true);
		}
Пример #15
0
        public void SetComplete_Should_RunContinuationIfOneIsPresent()
        {
            var taskSlim = new TaskSlim(null);

            taskSlim.IsCompleted.Should().BeFalse();
            taskSlim.HasContinuation.Should().BeFalse();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();

            var runCont = false;

            taskSlim.OnCompleted(() =>
            {
                runCont = true;
            });

            taskSlim.SetCompleted(runContinuationAsync: false);

            runCont.Should().BeTrue();
        }
Пример #16
0
        public void OnCompleted_Should_RunContinuationIfCompleted()
        {
            var taskSlim = new TaskSlim(null);

            taskSlim.IsCompleted.Should().BeFalse();
            taskSlim.HasContinuation.Should().BeFalse();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();

            taskSlim.SetCompleted(runContinuationAsync: false);

            var runCont = false;
            taskSlim.OnCompleted(() =>
            {
                runCont = true;
                taskSlim.GetResult();
            });

            runCont.Should().BeTrue();
        }
Пример #17
0
        internal TaskSlim __BasicPublishConfirm(string exchange, string routingKey, bool mandatory,
                                                BasicProperties properties, ArraySegment <byte> buffer)
        {
            if (properties == null)
            {
                properties = BasicProperties.Empty;
            }

            var confirmationKeeper = _channel._confirmationKeeper;

            TaskSlim tcs = _taskLightPool.GetObject();

            confirmationKeeper.WaitForSemaphore();             // make sure we're not over the limit

            var args = _basicPubArgsPool.GetObject();

            args.exchange   = exchange;
            args.routingKey = routingKey;
            args.mandatory  = mandatory;
            args.properties = properties;
            args.buffer     = buffer;

            _connectionIo.SendCommand(_channelNum, 60, 40,
                                      null, // AmqpChannelLevelFrameWriter.InternalBasicPublish,
                                      reply: (channel, classMethodId, error) =>
            {
                if (properties.IsReusable)
                {
                    _channel.Return(properties);                             // the tcs is left for the confirmation keeper
                }
                return(Task.CompletedTask);
            },
                                      expectsReply: false,
                                      tcsL: null,
                                      optArg: args,
                                      prepare: () => _channel._confirmationKeeper.Add(tcs));

            return(tcs);
        }
Пример #18
0
        internal static void SetException(TaskSlim tcs, AmqpError error, int classMethodId)
        {
            if (tcs == null)
            {
                return;
            }
            if (error != null)
            {
                tcs.SetException(new Exception("Error: " + error.ToErrorString()));
            }
            else if (classMethodId == 0)
            {
                tcs.SetException(new Exception("The server closed the connection"));
            }
            else
            {
                var classId  = classMethodId >> 16;
                var methodId = classMethodId & 0x0000FFFF;

                Console.WriteLine("Unexpected situation: classId = " + classId + " method " + methodId + " and error = null");
                tcs.SetException(new Exception("Unexpected reply from the server: classId = " + classId + " method " + methodId));
            }
        }
Пример #19
0
        internal void SendCommand(ushort channel, ushort classId, ushort methodId,
                                  Action <AmqpPrimitivesWriter, ushort, ushort, ushort, object> commandWriter,
                                  Func <ushort, int, AmqpError, Task> reply,
                                  bool expectsReply, TaskCompletionSource <bool> tcs = null,
                                  object optArg = null, TaskSlim tcsL = null, Action prepare = null)
        {
            if (_lastError != null)
            {
                // ConnClose and Channel close el al, are allowed to move fwd.
                var cmdId = (classId << 16) | methodId;
                if (cmdId != AmqpClassMethodConnectionLevelConstants.ConnectionClose &&
                    cmdId != AmqpClassMethodConnectionLevelConstants.ConnectionCloseOk &&
                    cmdId != AmqpClassMethodChannelLevelConstants.ChannelClose &&
                    cmdId != AmqpClassMethodChannelLevelConstants.ChannelCloseOk)
                {
                    SetErrorResultIfErrorPending(expectsReply, reply, tcs, tcsL);
                    return;
                }
            }

            var cmd = _cmdToSendObjPool.GetObject();

            // var cmd = new CommandToSend(null);
            cmd.Channel          = channel;
            cmd.ClassId          = classId;
            cmd.MethodId         = methodId;
            cmd.ReplyAction      = reply;
            cmd.commandGenerator = commandWriter;
            cmd.ExpectsReply     = expectsReply;
            cmd.Tcs           = tcs;
            cmd.TcsSlim       = tcsL;
            cmd.OptionalArg   = optArg;
            cmd.PrepareAction = prepare;

            _commandOutbox.Enqueue(cmd);
            _commandOutboxEvent.Set();
        }
Пример #20
0
        public void OnCompleted_Should_RunContinuationIfCompletedWithException()
        {
            var taskSlim = new TaskSlim(null);

            taskSlim.IsCompleted.Should().BeFalse();
            taskSlim.HasContinuation.Should().BeFalse();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();

            taskSlim.SetException(new Exception("nope"), runContinuationAsync: false);

            var runCont = false;
            taskSlim.OnCompleted(() =>
            {
                runCont = true;

                Assert.Throws<Exception>(() =>
                {
                    taskSlim.GetResult(); // throws the exception
                });
            });

            runCont.Should().BeTrue();
        }
Пример #21
0
        public void SetCompleted_Should_setCompletedFlags()
        {
            var taskSlim = new TaskSlim(null);

            taskSlim.IsCompleted.Should().BeFalse();
            taskSlim.HasContinuation.Should().BeFalse();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();

            taskSlim.SetCompleted(runContinuationAsync: false);

            taskSlim.IsCompleted.Should().BeTrue();
            taskSlim.HasContinuation.Should().BeFalse();
            taskSlim.HasException.Should().BeFalse();
            taskSlim.RunContinuationAsync.Should().BeFalse();
        }
Пример #22
0
		public void Dispose()
		{
			Channel = ClassId = MethodId = 0;
			commandGenerator = null;
			ReplyAction = null;
			ExpectsReply = false;
			OptionalArg = null;
			PrepareAction = null;
			Tcs = null;
			TcsSlim = null;
		}
Пример #23
0
		internal void SendCommand(ushort channel, ushort classId, ushort methodId,
			Action<AmqpPrimitivesWriter, ushort, ushort, ushort, object> commandWriter,
			Func<ushort, int, AmqpError, Task> reply,
			bool expectsReply, TaskCompletionSource<bool> tcs = null,
			object optArg = null, TaskSlim tcsL = null, Action prepare = null)
		{
			if (_lastError != null)
			{
				// ConnClose and Channel close el al, are allowed to move fwd. 
				var cmdId = (classId << 16) | methodId;
				if (cmdId != AmqpClassMethodConnectionLevelConstants.ConnectionClose &&
				    cmdId != AmqpClassMethodConnectionLevelConstants.ConnectionCloseOk &&
					cmdId != AmqpClassMethodChannelLevelConstants.ChannelClose &&
				    cmdId != AmqpClassMethodChannelLevelConstants.ChannelCloseOk)
				{
					SetErrorResultIfErrorPending(expectsReply, reply, tcs, tcsL); 
					return;
				}
			}

			var cmd = _cmdToSendObjPool.GetObject();
			// var cmd = new CommandToSend(null);
			cmd.Channel = channel;
			cmd.ClassId = classId;
			cmd.MethodId = methodId;
			cmd.ReplyAction = reply;
			cmd.commandGenerator = commandWriter;
			cmd.ExpectsReply = expectsReply;
			cmd.Tcs = tcs;
			cmd.TcsSlim = tcsL;
			cmd.OptionalArg = optArg;
			cmd.PrepareAction = prepare;

			_commandOutbox.Enqueue(cmd);
			_commandOutboxEvent.Set();
		}
Пример #24
0
		private void SetErrorResultIfErrorPending(bool expectsReply, Func<ushort, int, AmqpError, Task> replyFn, 
												  TaskCompletionSource<bool> tcs, TaskSlim taskSlim)
		{
			if (expectsReply)
			{
				replyFn(0, 0, _lastError);
			}
			else
			{
				AmqpIOBase.SetException(tcs, _lastError, 0);
				AmqpIOBase.SetException(taskSlim, _lastError, 0);
			}
		}
Пример #25
0
		private bool SecureSpotAndUniqueCorrelationId(TaskSlim<MessageDelivery> task, out uint correlationId)
		{
			correlationId = 0;

			var tries = 0;
			while (tries++ < _maxConcurrentCalls)
			{
				var correlationIndex = _correlationCounter++;
				var pos = correlationIndex % _maxConcurrentCalls;

				if (Interlocked.CompareExchange(ref _pendingCalls[pos], task, null) == null)
				{
					correlationId = correlationIndex;
					return true;
				}
			}

			return false;
		}