From dffa8061c3d0b275c0363f4ccf6412ebb8304f07 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Tue, 8 Nov 2016 15:22:41 +0300 Subject: [PATCH 1/2] APNS Queue to ConcurrentQueue --- PushSharp.Apple/ApnsConnection.cs | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/PushSharp.Apple/ApnsConnection.cs b/PushSharp.Apple/ApnsConnection.cs index 0908b166..618eae01 100644 --- a/PushSharp.Apple/ApnsConnection.cs +++ b/PushSharp.Apple/ApnsConnection.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using System.Security.Cryptography.X509Certificates; using System.Collections.Generic; +using System.Collections.Concurrent; using System.Threading; using System.Net; using PushSharp.Core; @@ -68,22 +69,22 @@ public ApnsConnection (ApnsConfiguration configuration) byte[] buffer = new byte[6]; int id; - SemaphoreSlim connectingSemaphore = new SemaphoreSlim (1); SemaphoreSlim batchSendSemaphore = new SemaphoreSlim (1); - object notificationBatchQueueLock = new object (); + object timerBatchWaitLock = new object (); //readonly object connectingLock = new object (); - Queue notifications = new Queue (); + ConcurrentQueue notifications = new ConcurrentQueue(); List sent = new List (); Timer timerBatchWait; public void Send (CompletableApnsNotification notification) { - lock (notificationBatchQueueLock) { - notifications.Enqueue (notification); + notifications.Enqueue(notification); + + lock (timerBatchWaitLock) { if (notifications.Count >= Configuration.InternalBatchSize) { @@ -113,15 +114,19 @@ async Task SendBatch () // Pause the timer timerBatchWait.Change (Timeout.Infinite, Timeout.Infinite); - if (notifications.Count <= 0) + if (notifications.IsEmpty) return; // Let's store the batch items to send internally var toSend = new List (); - while (notifications.Count > 0 && toSend.Count < Configuration.InternalBatchSize) { - var n = notifications.Dequeue (); - toSend.Add (n); + while (!notifications.IsEmpty && toSend.Count < Configuration.InternalBatchSize) { + + CompletableApnsNotification n; + if (notifications.TryDequeue (out n)) + { + toSend.Add(n); + } } From aeaecf7df2d4cfb4a867ba080e16abe611876b30 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Tue, 8 Nov 2016 16:44:20 +0300 Subject: [PATCH 2/2] APNS Queue to ConcurrentQueue: remove lock --- PushSharp.Apple/ApnsConnection.cs | 35 +++++++++++++------------------ 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/PushSharp.Apple/ApnsConnection.cs b/PushSharp.Apple/ApnsConnection.cs index 618eae01..a2bb7a8f 100644 --- a/PushSharp.Apple/ApnsConnection.cs +++ b/PushSharp.Apple/ApnsConnection.cs @@ -71,8 +71,7 @@ public ApnsConnection (ApnsConfiguration configuration) SemaphoreSlim connectingSemaphore = new SemaphoreSlim (1); SemaphoreSlim batchSendSemaphore = new SemaphoreSlim (1); - object timerBatchWaitLock = new object (); - + //readonly object connectingLock = new object (); ConcurrentQueue notifications = new ConcurrentQueue(); List sent = new List (); @@ -81,26 +80,22 @@ public ApnsConnection (ApnsConfiguration configuration) public void Send (CompletableApnsNotification notification) { - notifications.Enqueue(notification); - - lock (timerBatchWaitLock) { - - if (notifications.Count >= Configuration.InternalBatchSize) { - - // Make the timer fire immediately and send a batch off - timerBatchWait.Change (0, Timeout.Infinite); - return; - } - - // Restart the timer to wait for more notifications to be batched - // This timer will keep getting 'restarted' before firing as long as notifications - // are queued before the timer's due time - // if the timer is actually called, it means no more notifications were queued, - // so we should flush out the queue instead of waiting for more to be batched as they - // might not ever come and we don't want to leave anything stranded in the queue - timerBatchWait.Change (Configuration.InternalBatchingWaitPeriod, Timeout.InfiniteTimeSpan); + + if (notifications.Count >= Configuration.InternalBatchSize) { + + // Make the timer fire immediately and send a batch off + timerBatchWait.Change (0, Timeout.Infinite); + return; } + + // Restart the timer to wait for more notifications to be batched + // This timer will keep getting 'restarted' before firing as long as notifications + // are queued before the timer's due time + // if the timer is actually called, it means no more notifications were queued, + // so we should flush out the queue instead of waiting for more to be batched as they + // might not ever come and we don't want to leave anything stranded in the queue + timerBatchWait.Change (Configuration.InternalBatchingWaitPeriod, Timeout.InfiniteTimeSpan); } long batchId = 0;