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"); }
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(); }
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 Dispose() { Channel = ClassId = MethodId = 0; commandGenerator = null; ReplyAction = null; ExpectsReply = false; OptionalArg = null; PrepareAction = null; Tcs = null; TcsSlim = null; }
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(); }
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"); } }
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"); }
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(); }
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); }
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(); }
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(); }
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); }
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)); } }
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(); }
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(); }
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(); }
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(); }
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); } }
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; }