//
//  RunLoopTransactions.m
//  SDWebImage
//
//  Created by 鍒樺井 on 16/4/1.
//  Copyright 漏 2016骞?Dailymotion. All rights reserved.
//

#import "RunLoopTransactions.h"


@interface RunLoopTransactions ()

@property (nonatomic, strong) id target;
@property (nonatomic, assign) SEL selector;
@property (nonatomic, strong) id object;

@end


static NSMutableSet* transactionSet = nil;

static void RunLoopObserverCallBack(CFRunLoopObserverRef observer,
                                    CFRunLoopActivity activity,
                                    void *info) {
    if (transactionSet.count == 0) return;
    NSSet* currentSet = transactionSet;
    transactionSet = [[NSMutableSet alloc] init];
    [currentSet enumerateObjectsUsingBlock:^(RunLoopTransactions* transactions, BOOL* stop) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [transactions.target performSelector:transactions.selector withObject:transactions.object];
#pragma clang diagnostic pop
    }];
}

static void RunLoopTransactionsSetup() {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        transactionSet = [[NSMutableSet alloc] init];
        CFRunLoopRef runloop = CFRunLoopGetMain();
        CFRunLoopObserverRef observer;
        observer = CFRunLoopObserverCreate(CFAllocatorGetDefault(),
                                           kCFRunLoopBeforeWaiting | kCFRunLoopExit,
                                           true,
                                           0xFFFFFF,
                                           RunLoopObserverCallBack, NULL);
        CFRunLoopAddObserver(runloop, observer, kCFRunLoopCommonModes);
        CFRelease(observer);
    });
}


@implementation RunLoopTransactions


+ (RunLoopTransactions *)transactionsWithTarget:(id)target
                                       selector:(SEL)selector
                                         object:(id)object {
    if (!target || !selector) {
        return nil;
    }
    RunLoopTransactions* transactions = [[RunLoopTransactions alloc] init];
    transactions.target = target;
    transactions.selector = selector;
    transactions.object = object;
    return transactions;
}

- (void)commit {
    if (!_target || !_selector) {
        return;
    }
    RunLoopTransactionsSetup();
    [transactionSet addObject:self];
}

- (NSUInteger)hash {
    long v1 = (long)((void *)_selector);
    long v2 = (long)_target;
    return v1 ^ v2;
}

- (BOOL)isEqual:(id)object{
    if (self == object) {
        return YES;
    }
    if (![object isMemberOfClass:self.class]){
        return NO;
    }
    RunLoopTransactions* other = object;
    return other.selector == _selector && other.target == _target;
}



@end
// 鐗堟潈灞炰簬鍘熶綔鑰?// http://code4app.com (cn) http://code4app.net (en)
// 鍙戝竷浠g爜浜庢渶涓撲笟鐨勬簮鐮佸垎浜綉绔? Code4App.com