Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 52 additions & 41 deletions Sources/Core/QTEventBus.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,28 @@
//

#import "QTEventBus.h"
#import <pthread.h>
#import <os/lock.h>
#import <objc/runtime.h>
#import "NSObject+QTEventBus.h"
#import "QTEventBusCollection.h"
#import "NSNotification+QTEvent.h"
#import "NSObject+QTEventBus_Private.h"

static inline NSString * __generateUnqiueKey(Class<QTEvent> cls,NSString * eventType){
static inline NSString * __generateUniqueKey(Class<QTEvent> cls, NSString * eventType){
Class targetClass = [cls respondsToSelector:@selector(eventClass)] ? [cls eventClass] : cls;
if (eventType) {
return [NSString stringWithFormat:@"%@_of_%@",eventType,NSStringFromClass(targetClass)];
}else{
return [NSString stringWithFormat:@"%@_of_%@", eventType, NSStringFromClass(targetClass)];
} else {
return NSStringFromClass(targetClass);
}
}

static inline NSString * __generateUniqueId(void) {
u_int64_t timestamp = (u_int64_t)([[NSDate date] timeIntervalSince1970] * 1000000);
u_int32_t random = arc4random();
return [NSString stringWithFormat:@"%llu_%u", timestamp, random];
}

/**
内存中保存的监听者
*/
Expand All @@ -35,13 +41,13 @@ - (instancetype)initWithEventBus:(QTEventBus *)eventBus

@property (strong, nonatomic) NSObject * lifeTimeTracker;

@property (strong, nonatomic) dispatch_queue_t queue;
@property (assign, nonatomic) dispatch_queue_t queue;

@property (strong, nonatomic) NSMutableArray * eventSubTypes;

@property (strong, nonatomic) QTEventBus * eventBus;

@property (copy, nonatomic) void(^hander)(__kindof NSObject *);
@property (copy, nonatomic) void(^handler)(__kindof NSObject *);

@end

Expand All @@ -55,7 +61,7 @@ @interface _QTEventSubscriber: NSObject<QTEventBusContainerValue>

@property (copy, nonatomic) void (^handler)(__kindof NSObject *);

@property (strong, nonatomic) dispatch_queue_t queue;
@property (assign, nonatomic) dispatch_queue_t queue;

@property (copy, nonatomic) NSString * uniqueId;

Expand Down Expand Up @@ -144,7 +150,7 @@ - (void)dispose{


@interface QTEventBus(){
pthread_mutex_t _accessLock;
os_unfair_lock_t _accessLock;
}

@property (copy, nonatomic) NSString * prefix;
Expand All @@ -153,7 +159,7 @@ @interface QTEventBus(){

@property (strong, nonatomic) dispatch_queue_t publishQueue;

@property (strong, nonatomic) NSMutableDictionary * notificationTracker;
@property (strong, nonatomic) NSMutableDictionary<NSString *, NSNumber *> * notificationTracker;

@end

Expand All @@ -174,32 +180,33 @@ - (instancetype)init{
_collection = [[QTEventBusCollection alloc] init];
_publishQueue = dispatch_queue_create("com.eventbus.publish.queue", DISPATCH_QUEUE_SERIAL);
_notificationTracker = [[NSMutableDictionary alloc] init];
pthread_mutex_init(&_accessLock, NULL);
_accessLock = OS_UNFAIR_LOCK_INIT;
}
return self;
}

- (void)lockAndDo:(void(^)(void))block{
os_unfair_lock_lock(_accessLock);
@try{
pthread_mutex_lock(&_accessLock);
block();
}@finally{
pthread_mutex_unlock(&_accessLock);
os_unfair_lock_unlock(_accessLock);
}
}

#pragma mark - Normal Event


- (id<QTEventToken>)_createNewSubscriber:(QTEventSubscriberMaker *)maker{
if (!maker.hander) {
if (!maker.handler) {
return nil;
}
NSMutableArray * tokens;
if (maker.eventSubTypes.count == 0) {//一级事件
_QTEventToken * token = [self _addSubscriberWithMaker:maker eventType:nil];
return token;
}
NSMutableArray * tokens = [[NSMutableArray alloc] init];
tokens = [[NSMutableArray alloc] initWithCapacity:maker.eventSubTypes.count];
for (NSString * eventType in maker.eventSubTypes) {
_QTEventToken * token = [self _addSubscriberWithMaker:maker eventType:eventType];
[tokens addObject:token];
Expand All @@ -211,17 +218,24 @@ - (void)lockAndDo:(void(^)(void))block{
- (void)_addNotificationObserverIfNeeded:(NSString *)name{
if (!name) { return; }
[self lockAndDo:^{
if ([self.notificationTracker objectForKey:name]) {
NSNumber * count = self.notificationTracker[name];
if (count && count.integerValue > 0) {
self.notificationTracker[name] = @(count.integerValue + 1);
return;
}
[self.notificationTracker setObject:@(1) forKey:name];
self.notificationTracker[name] = @(1);
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:name object:nil];
}];
}

- (void)_removeNotificationObserver:(NSString *)name{
if (!name) { return; }
[self lockAndDo:^{
NSNumber * count = self.notificationTracker[name];
if (count && count.integerValue > 1) {
self.notificationTracker[name] = @(count.integerValue - 1);
return;
}
[self.notificationTracker removeObjectForKey:name];
@try{
[[NSNotificationCenter defaultCenter] removeObserver:self name:name object:nil];
Expand All @@ -232,12 +246,12 @@ - (void)_removeNotificationObserver:(NSString *)name{

- (_QTEventToken *)_addSubscriberWithMaker:(QTEventSubscriberMaker *)maker eventType:(NSString *)eventType{
__weak typeof(self) weakSelf = self;
NSString * eventKey = __generateUnqiueKey(maker.eventClass, eventType);
NSString * eventKey = __generateUniqueKey(maker.eventClass, eventType);
NSString * groupId = [self.prefix stringByAppendingString:eventKey];
NSString * uniqueId = [groupId stringByAppendingString:@([NSDate date].timeIntervalSince1970).stringValue];
NSString * uniqueId = [groupId stringByAppendingString:__generateUniqueId()];
_QTEventToken * token = [[_QTEventToken alloc] initWithKey:uniqueId];
BOOL isCFNotifiction = (maker.eventClass == [NSNotification class]);
if (eventType && isCFNotifiction) {
BOOL isNSNotification = (maker.eventClass == [NSNotification class]);
if (eventType && isNSNotification) {
[self _addNotificationObserverIfNeeded:eventType];
}
token.onDispose = ^(NSString *uniqueId) {
Expand All @@ -246,14 +260,14 @@ - (_QTEventToken *)_addSubscriberWithMaker:(QTEventSubscriberMaker *)maker event
return;
}
BOOL empty = [strongSelf.collection removeUniqueId:uniqueId ofKey:groupId];
if (empty && isCFNotifiction) {
if (empty && isNSNotification) {
[strongSelf _removeNotificationObserver:eventType];
}
};
//创建监听者
_QTEventSubscriber * subscriber = [[_QTEventSubscriber alloc] init];
subscriber.queue = maker.queue;
subscriber.handler = maker.hander;
subscriber.handler = maker.handler;
subscriber.uniqueId = uniqueId;
if (maker.lifeTimeTracker) {
[maker.lifeTimeTracker.eb_disposeBag addToken:token];
Expand All @@ -273,8 +287,8 @@ - (_QTEventToken *)_addSubscriberWithMaker:(QTEventSubscriberMaker *)maker event
return [[QTEventSubscriberMaker alloc] initWithEventBus:self eventClass:eventClass];
}

- (void)receiveNotification:(NSNotification *)notificaion{
[self dispatch:notificaion];
- (void)receiveNotification:(NSNotification *)notification{
[self dispatch:notification];
}

- (void)dispatch:(id<QTEvent>)event{
Expand All @@ -284,11 +298,11 @@ - (void)dispatch:(id<QTEvent>)event{
NSString * eventSubType = [event respondsToSelector:@selector(eventSubType)] ? [event eventSubType] : nil;
if (eventSubType) {
//二级事件
NSString * key = __generateUnqiueKey(event.class, eventSubType);
NSString * key = __generateUniqueKey(event.class, eventSubType);
[self _publishKey:key event:event];
}
//一级事件
NSString * key = __generateUnqiueKey(event.class, nil);
NSString * key = __generateUniqueKey(event.class, nil);
[self _publishKey:key event:event];
}

Expand All @@ -315,18 +329,17 @@ - (void)_publishKey:(NSString *)eventKey event:(NSObject *)event{
return;
}
for (_QTEventSubscriber * subscriber in subscribers) {
if (subscriber.queue) { //异步分发
void(^handler)(NSObject *) = subscriber.handler;
if (!handler) {
continue;
}
if (subscriber.queue) {
dispatch_async(subscriber.queue, ^{
if (subscriber.handler) {
subscriber.handler(event);
}
handler(event);
});
}else{ //同步分发
if (subscriber.handler) {
subscriber.handler(event);
}
} else {
handler(event);
}

}
}

Expand All @@ -351,8 +364,8 @@ - (instancetype)initWithEventBus:(QTEventBus *)eventBus
return self;
}

- (id<QTEventToken>)next:(QTEventNextBlock)hander{
return self.next(hander);
- (id<QTEventToken>)next:(QTEventNextBlock)block{
return self.next(block);
}

- (QTEventSubscriberMaker *)atQueue:(dispatch_queue_t)queue{
Expand Down Expand Up @@ -396,12 +409,10 @@ - (QTEventSubscriberMaker *)ofSubType:(NSString *)eventType{
}

- (id<QTEventToken>(^)(void(^)(id event)))next{
return ^id<QTEventToken>(void(^hander)(__kindof NSObject * event)){
self.hander = hander;
return ^id<QTEventToken>(void(^block)(__kindof NSObject * event)){
self.handler = block;
return [self.eventBus _createNewSubscriber:self];
};
}

@end


50 changes: 26 additions & 24 deletions Sources/Core/QTEventBusCollection.m
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//

#import "QTEventBusCollection.h"
#include <pthread.h>
#include <os/lock.h>

@class _QTEventBusLinkNode;
/**
Expand Down Expand Up @@ -73,10 +73,10 @@ - (BOOL)isEmpty{
*/
- (void)removeNodeForId:(NSString *)uniqueId{
//不存在
if (![_registeredNodeTable objectForKey:uniqueId]) {
_QTEventBusLinkNode * node = [_registeredNodeTable objectForKey:uniqueId];
if (!node) {
return;
}
_QTEventBusLinkNode * node = [_registeredNodeTable objectForKey:uniqueId];
if (node == _head) {
_head = _head.next;
}
Expand All @@ -87,8 +87,12 @@ - (void)removeNodeForId:(NSString *)uniqueId{
_QTEventBusLinkNode * nextNode = node.next;
node.next = nil;
node.previous = nil;
previousNode.next = nextNode;
nextNode.previous = previousNode;
if (previousNode) {
previousNode.next = nextNode;
}
if (nextNode) {
nextNode.previous = previousNode;
}
[_registeredNodeTable removeObjectForKey:uniqueId];
}

Expand Down Expand Up @@ -132,17 +136,17 @@ - (NSArray *)toArray{
}
pointer = pointer.next;
}
return [[NSArray alloc] initWithArray:array];
return [array copy];
}

@end


@interface QTEventBusCollection(){
pthread_mutex_t _accessLock;
os_unfair_lock_t _accessLock;
}

@property (strong, nonatomic) NSMutableDictionary<NSString *,_QTEventBusLinkList *> * linkListTable;//记录key->链表的头
@property (strong, nonatomic) NSMutableDictionary<NSString *,_QTEventBusLinkList *> * linkListTable;

@end

Expand All @@ -152,49 +156,47 @@ @implementation QTEventBusCollection
- (instancetype)init{
if (self = [super init]) {
_linkListTable = [[NSMutableDictionary alloc] init];
pthread_mutex_init(&_accessLock, NULL);
_accessLock = OS_UNFAIR_LOCK_INIT;
}
return self;
}

- (void)lockAndDo:(void(^)(void))block{
os_unfair_lock_lock(_accessLock);
@try{
pthread_mutex_lock(&_accessLock);
block();
}@finally{
pthread_mutex_unlock(&_accessLock);
os_unfair_lock_unlock(_accessLock);
}
}

- (id)lockAndFetch:(id(^)(void))block{
id result;
os_unfair_lock_lock(_accessLock);
@try{
pthread_mutex_lock(&_accessLock);
result = block();
return block();
}@finally{
pthread_mutex_unlock(&_accessLock);
os_unfair_lock_unlock(_accessLock);
}
return result;
}

- (void)addObject:(id<QTEventBusContainerValue>)object forKey:(NSString *)key{
NSString * nodeUniqueKey = [object valueUniqueId];
[self lockAndDo:^{
_QTEventBusLinkList * linkList = [self.linkListTable objectForKey:key];
_QTEventBusLinkList * linkList = self.linkListTable[key];
_QTEventBusLinkNode * updateNode = [[_QTEventBusLinkNode alloc] initWithValue:object
uniqueId:nodeUniqueKey];
if (!linkList) {
linkList = [[_QTEventBusLinkList alloc] initWithNode:updateNode];
[self.linkListTable setObject:linkList forKey:key];
}else{
self.linkListTable[key] = linkList;
} else {
[linkList appendNode:updateNode];
}
}];
}

- (BOOL)removeUniqueId:(NSString *)uniqueId ofKey:(NSString *)key{
NSNumber * result = [self lockAndFetch:^id{
_QTEventBusLinkList * linkList = [self.linkListTable objectForKey:key];
_QTEventBusLinkList * linkList = self.linkListTable[key];
[linkList removeNodeForId:uniqueId];
if (linkList.isEmpty) {
[self.linkListTable removeObjectForKey:key];
Expand All @@ -208,11 +210,11 @@ - (BOOL)removeUniqueId:(NSString *)uniqueId ofKey:(NSString *)key{
返回一组值
*/
- (NSArray *)objectsForKey:(NSString *)key{
NSArray * arrary = [self lockAndFetch:^id{
_QTEventBusLinkList * linkList = [self.linkListTable objectForKey:key];
return linkList.toArray;
NSArray * array = [self lockAndFetch:^id{
_QTEventBusLinkList * linkList = self.linkListTable[key];
return [linkList toArray];
}];
return arrary;
return array;
}

@end