Private
Public Access
1
0

Batch updates, and fixing bug where daemon would crash when accessing IMCore stuff from different threads

This commit is contained in:
James Magahern
2018-11-21 15:51:51 -07:00
parent 3186f1948a
commit dba4910a82
10 changed files with 155 additions and 90 deletions

View File

@@ -10,6 +10,8 @@
#import "IMMessageItem+Encoded.h"
#import "IMChat+Encoded.h"
static const NSUInteger kUpdateItemsCullingLength = 100;
@interface MBIMUpdateItem (/*INTERNAL*/)
@property (nonatomic, assign) NSUInteger messageSequenceNumber;
@end
@@ -18,6 +20,9 @@
NSUInteger _messageSequenceNumber;
dispatch_queue_t _accessQueue;
NSMutableArray *_consumers;
// Maps message sequence number to update item
NSMutableDictionary<NSNumber *, MBIMUpdateItem *> *_updateItemHistory;
}
+ (instancetype)sharedInstance
@@ -38,16 +43,30 @@
_accessQueue = dispatch_queue_create("net.buzzert.MBIMUpdateQueue", DISPATCH_QUEUE_SERIAL);
_consumers = [[NSMutableArray alloc] init];
_messageSequenceNumber = 0;
_updateItemHistory = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)addConsumer:(MBIMUpdateConsumer)consumer
- (void)addConsumer:(MBIMUpdateConsumer)consumer withLastSyncedMessageSeq:(NSInteger)messageSeq
{
__weak NSMutableArray *consumers = _consumers;
__weak NSMutableDictionary *updateItemHistory = _updateItemHistory;
dispatch_async(_accessQueue, ^{
[consumers addObject:consumer];
if ((messageSeq >= 0) && messageSeq < self->_messageSequenceNumber) {
NSMutableArray *batchedUpdates = [NSMutableArray array];
for (NSUInteger seq = messageSeq + 1; seq <= self->_messageSequenceNumber; seq++) {
MBIMUpdateItem *item = [updateItemHistory objectForKey:@(seq)];
if (item) {
[batchedUpdates addObject:item];
}
}
consumer(batchedUpdates);
} else {
[consumers addObject:consumer];
}
});
}
@@ -61,16 +80,36 @@
- (void)enqueueUpdateItem:(MBIMUpdateItem *)item
{
_messageSequenceNumber++;
item.messageSequenceNumber = _messageSequenceNumber;
__weak NSMutableArray *consumers = _consumers;
__weak NSMutableDictionary *updateItemHistory = _updateItemHistory;
dispatch_async(_accessQueue, ^{
self->_messageSequenceNumber++;
item.messageSequenceNumber = self->_messageSequenceNumber;
for (MBIMUpdateConsumer consumer in consumers) {
consumer(item);
consumer(@[ item ]);
}
[consumers removeAllObjects];
[updateItemHistory setObject:item forKey:@(item.messageSequenceNumber)];
[self _cullUpdateItems];
});
}
- (void)_cullUpdateItems
{
__weak NSMutableDictionary *updateItemHistory = _updateItemHistory;
dispatch_async(_accessQueue, ^{
if ([updateItemHistory count] > kUpdateItemsCullingLength) {
NSArray *sortedKeys = [[updateItemHistory allKeys] sortedArrayUsingSelector:@selector(compare:)];
for (NSValue *key in sortedKeys) {
[updateItemHistory removeObjectForKey:key];
if ([updateItemHistory count] <= kUpdateItemsCullingLength) {
break;
}
}
}
});
}
@@ -80,7 +119,7 @@
- (NSDictionary *)dictionaryRepresentation
{
NSMutableDictionary *updateDict = [NSMutableDictionary dictionary];
updateDict[@"messageSequenceNumber"] = @(_messageSequenceNumber);
updateDict[@"messageSequenceNumber"] = @(self.messageSequenceNumber);
if ([self changedChat]) {
updateDict[@"conversation"] = [[self changedChat] mbim_dictionaryRepresentation];