Skip to content

Instantly share code, notes, and snippets.

@hankbao
Last active May 16, 2019 13:11
Show Gist options
  • Save hankbao/0d10ff7c762207ac23eb9a5a447a63fe to your computer and use it in GitHub Desktop.
Save hankbao/0d10ff7c762207ac23eb9a5a447a63fe to your computer and use it in GitHub Desktop.
Autorelease Pool which doesn't work...
//
// AutoreleasePool.h
//
// Created by Hank Bao
// Copyright (c) 2019 zTap studio. All rights reserved.
//
#ifndef AUTORELEASE_POOL_H
#define AUTORELEASE_POOL_H
#ifdef __cplusplus
extern "C" {
#endif // __clpusplus
#ifdef __APPLE__
void autoreleasepool_push(void);
void autoreleasepool_pop(void);
#define AUTORELEASEPOOL_PUSH() autoreleasepool_push()
#define AUTORELEASEPOOL_POP() autoreleasepool_pop()
#else
#define AUTORELEASEPOOL_PUSH()
#define AUTORELEASEPOOL_POP()
#endif // __APPLE__
#ifdef __cplusplus
}
#endif // __clpusplus
#endif AUTORELEASE_POOL_H
//
// AutoreleasePool.m
//
// Created by Hank Bao
// Copyright (c) 2019 zTap studio. All rights reserved.
//
@import Foundation;
#import "AutoreleasePool.h"
static NSString * const kAutoreleasePoolThreadDictionaryKey = @"net.ztap.autoreleasepool";
static NSString * const kAutoreleasePoolException = @"net.ztap.exception.autoreleasepool";
static void* _autorelease_pool_class;
typedef void* (*pool_imp_new)(void*, void*);
static pool_imp_new _autorelease_pool_imp_new;
static SEL _autorelease_pool_sel_new;
typedef void (*pool_imp_drain)(void*, void*);
static pool_imp_drain _autorelease_pool_imp_drain;
static SEL _autorelease_pool_sel_drain;
@interface AutoreleasePoolWrapper : NSObject {
void* payload; // the real pool
}
@end
@implementation AutoreleasePoolWrapper
- (instancetype)init {
if (self = [super init]) {
payload = _autorelease_pool_imp_new(_autorelease_pool_class, _autorelease_pool_sel_new);
}
return self;
}
- (void)dealloc {
if (payload) {
_autorelease_pool_imp_drain(payload, _autorelease_pool_sel_drain);
payload = NULL;
}
}
@end
@interface AutoreleasePool : NSObject
+ (void)push;
+ (void)pop;
@end
@implementation AutoreleasePool
+ (void)initialize {
if (self == [AutoreleasePool self]) {
_autorelease_pool_class = (__bridge void *)(NSClassFromString(@"NSAutoreleasePool"));
_autorelease_pool_sel_new = @selector(new);
_autorelease_pool_imp_new = (pool_imp_new) [NSClassFromString(@"NSAutoreleasePool")
methodForSelector:_autorelease_pool_sel_new];
_autorelease_pool_sel_drain = @selector(drain);
_autorelease_pool_imp_drain = (pool_imp_drain) [NSClassFromString(@"NSAutoreleasePool")
instanceMethodForSelector:_autorelease_pool_sel_drain];;
}
}
+ (NSMutableArray*)poolsForCurrentThread {
NSMutableDictionary* threadDict = NSThread.currentThread.threadDictionary;
NSMutableArray* pools = threadDict[kAutoreleasePoolThreadDictionaryKey];
if (!pools) {
pools = [NSMutableArray new];
threadDict[kAutoreleasePoolThreadDictionaryKey] = pools;
}
return pools;
}
+ (void)push {
AutoreleasePoolWrapper* pool = [AutoreleasePoolWrapper new];
if (pool) {
[[self poolsForCurrentThread] addObject:pool];
}
}
+ (void)pop {
NSMutableArray* pools = [self poolsForCurrentThread];
if (!pools.lastObject) {
[NSException raise:kAutoreleasePoolException format:@"autoreleasepool unbalanced pop"];
}
[pools removeLastObject];
}
@end
void autoreleasepool_push(void) {
[AutoreleasePool push];
}
void autoreleasepool_pop(void) {
[AutoreleasePool pop];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment