public override BaseLightStream CloneStream(int bodySize) { return(new MemoryStream2(BufferUtil.Copy(this, bodySize))); }
internal async Task DispatchDeliveredMessage(string consumerTag, ulong deliveryTag, bool redelivered, string exchange, string routingKey, int bodySize, BasicProperties properties, Stream stream) { BasicConsumerSubscriptionInfo consumer; if (_consumerSubscriptions.TryGetValue(consumerTag, out consumer)) { var delivery = new MessageDelivery() { bodySize = bodySize, properties = properties, routingKey = routingKey, deliveryTag = deliveryTag, redelivered = redelivered }; var mode = consumer.Mode; var cb = consumer.Callback; var consumerInstance = consumer._consumer; if (mode == ConsumeMode.SingleThreaded) { // run with scissors, we're letting // the user code mess with the ring buffer in the name of performance delivery.stream = stream; // upon return it's assumed the user has consumed from the stream and is done with it try { if (cb != null) { await cb(delivery); } else { await consumerInstance.Consume(delivery); } } finally { // fingers crossed the user cloned the buffer if she needs it later this.Return(properties); } } else { // parallel mode. it cannot hold the frame handler, so we copy the buffer (yuck) and more forward // since we dont have any control on how the user // will deal with the buffer we cant even re-use/use a pool, etc :-( // Idea: split Ringbuffer consumers, create reader barrier. once they are all done, // move the read pos forward. Shouldnt be too hard to implement and // avoids the new buffer + GC and keeps the api Stream based consistently if (mode == ConsumeMode.ParallelWithBufferCopy) { var bufferCopy = BufferUtil.Copy(stream as RingBufferStreamAdapter, (int)bodySize); var memStream = new MemoryStream(bufferCopy, writable: false); delivery.stream = memStream; } // else if (mode == ConsumeMode.ParallelWithReadBarrier) // { // var readBarrier = new RingBufferStreamReadBarrier(stream as RingBufferStreamAdapter, delivery.bodySize); // delivery.stream = readBarrier; // } #pragma warning disable 4014 Task.Factory.StartNew(async() => // ThreadPool.UnsafeQueueUserWorkItem((param) => #pragma warning restore 4014 { try { using (delivery.stream) { if (cb != null) { await cb(delivery); } else { await consumerInstance.Consume(delivery); } } } catch (Exception e) { Console.WriteLine("From threadpool " + e); } finally { this.Return(properties); } }, TaskCreationOptions.PreferFairness); } } else { // received msg but nobody was subscribed to get it (?) TODO: log it at least } }