Last active
August 29, 2015 14:15
-
-
Save TheFox/1c4984523df14f2ff5f8 to your computer and use it in GitHub Desktop.
Objc call_category_loads
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Original: http://www.opensource.apple.com/source/objc4/objc4-646/runtime/objc-loadmethod.mm | |
static BOOL call_category_loads(void){ | |
// ... | |
int used = loadable_categories_used; | |
// ... | |
loadable_categories_used = 0; | |
// ... | |
new_categories_added = (loadable_categories_used > 0); | |
for (i = 0; i < loadable_categories_used; i++) { | |
if (used == allocated) { | |
allocated = allocated*2 + 16; | |
cats = (struct loadable_category *) | |
_realloc_internal(cats, allocated * sizeof(struct loadable_category)); | |
} | |
cats[used++] = loadable_categories[i]; | |
} | |
if (loadable_categories) _free_internal(loadable_categories); | |
if (used) { | |
loadable_categories = cats; | |
// ... | |
} else { | |
// ... | |
loadable_categories = nil; | |
// ... | |
} | |
// ... | |
return new_categories_added; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Created @ 16.02.2015 by Christian Mayer <http://fox21.at> | |
Compile with | |
clang++ -I darwin/objc4-646/runtime my_call_category_loads.cpp -o my_call_category_loads | |
*/ | |
#include <stdio.h> | |
#include <unistd.h> | |
#include <cstddef> | |
#include <objc/objc.h> | |
#if __OBJC2__ | |
typedef struct method_t *Method; | |
typedef struct ivar_t *Ivar; | |
typedef struct category_t *Category; | |
typedef struct property_t *objc_property_t; | |
#else | |
typedef struct old_method *Method; | |
typedef struct old_ivar *Ivar; | |
typedef struct old_category *Category; | |
typedef struct old_property *objc_property_t; | |
#endif | |
typedef void(*load_method_t)(id, SEL); | |
struct loadable_class { | |
Class cls; | |
IMP method; | |
}; | |
struct loadable_category { | |
Category cat; | |
IMP method; | |
}; | |
static struct loadable_class *loadable_classes = nil; | |
static int loadable_classes_used = 0; | |
static int loadable_classes_allocated = 0; | |
static struct loadable_category *loadable_categories = nil; | |
static int loadable_categories_used = 0; | |
static int loadable_categories_allocated = 0; | |
static void my_call_class_loads(void){ | |
puts("exec my_call_class_loads()"); | |
int i; | |
struct loadable_class *classes = loadable_classes; | |
int used = loadable_classes_used; | |
loadable_classes = nil; | |
loadable_classes_allocated = 0; | |
loadable_classes_used = 0; | |
for(i = 0; i < used; i++){ | |
//sleep(1); | |
printf("\t iterate 'used': %d\n", i); | |
/* | |
Class cls = classes[i].cls; | |
load_method_t load_method = (load_method_t)classes[i].method; | |
if(!cls) | |
continue; | |
if(PrintLoading){ | |
_objc_inform("LOAD: +[%s load]\n", cls->nameForLogging()); | |
} | |
(*load_method)(cls, SEL_load);*/ | |
} | |
//if(classes) _free_internal(classes); | |
puts(""); | |
} | |
static BOOL my_call_category_loads(void){ | |
puts("exec my_call_category_loads()"); | |
int i, shift; | |
BOOL new_categories_added = NO; | |
struct loadable_category *cats = loadable_categories; | |
int used = loadable_categories_used; | |
int allocated = loadable_categories_allocated; | |
loadable_categories = nil; | |
loadable_categories_allocated = 0; | |
loadable_categories_used = 0; | |
for(i = 0; i < used; i++){ | |
//sleep(1); | |
printf("\t iterate 'used' A: %d\n", i); | |
/* | |
Category cat = cats[i].cat; | |
load_method_t load_method = (load_method_t)cats[i].method; | |
Class cls; | |
if(!cat) | |
continue; | |
cls = _category_getClass(cat); | |
if(cls && cls->isLoadable()){ | |
if(PrintLoading){ | |
_objc_inform("LOAD: +[%s(%s) load]\n", cls->nameForLogging(), _category_getName(cat)); | |
} | |
(*load_method)(cls, SEL_load); | |
cats[i].cat = nil; | |
}*/ | |
} | |
shift = 0; | |
for(i = 0; i < used; i++){ | |
//sleep(1); | |
printf("\t iterate 'used' B: %d\n", i); | |
/*if(cats[i].cat){ | |
cats[i-shift] = cats[i]; | |
} | |
else{ | |
shift++; | |
}*/ | |
} | |
used -= shift; | |
printf("\t used: %d\n", used); | |
printf("\t loadable_categories_used: %d\n", loadable_categories_used); | |
new_categories_added = (loadable_categories_used > 0); | |
//new_categories_added = (used > 0); | |
for(i = 0; i < loadable_categories_used; i++){ | |
//for(i = 0; i < used; i++){ | |
//sleep(1); | |
printf("\t iterate 'loadable_categories_used': %d %d\n", i, allocated); | |
if(used == allocated){ | |
allocated = allocated * 2 + 16; | |
printf("\t allocated: %d\n", allocated); | |
//cats = (struct loadable_category *)_realloc_internal(cats, allocated * sizeof(struct loadable_category)); | |
printf("\t cats = ... _realloc_internal(...);\n"); | |
} | |
//cats[used++] = loadable_categories[i]; | |
} | |
printf("\t loadable_categories: %p\n", loadable_categories); | |
if(loadable_categories) | |
//_free_internal(loadable_categories); | |
printf("\t _free_internal(loadable_categories);\n"); | |
if(used){ | |
loadable_categories = cats; | |
loadable_categories_used = used; | |
loadable_categories_allocated = allocated; | |
} | |
else{ | |
if(cats) | |
//_free_internal(cats); | |
printf("\t _free_internal(cats);\n"); | |
loadable_categories = nil; | |
loadable_categories_used = 0; | |
loadable_categories_allocated = 0; | |
} | |
/*if(PrintLoading){ | |
if(loadable_categories_used != 0){ | |
_objc_inform("LOAD: %d categories still waiting for +load\n", loadable_categories_used); | |
} | |
}*/ | |
printf("\t new_categories_added: %d\n", new_categories_added); | |
puts(""); | |
return new_categories_added; | |
} | |
void my_call_load_methods(void){ | |
static BOOL loading = NO; | |
BOOL more_categories; | |
//recursive_mutex_assert_locked(&loadMethodLock); | |
if (loading) return; | |
loading = YES; | |
//void *pool = objc_autoreleasePoolPush(); | |
do{ | |
while(loadable_classes_used > 0){ | |
printf("call my_call_class_loads() in my_call_load_methods(): %d\n", loadable_classes_used); | |
my_call_class_loads(); | |
//sleep(1); | |
} | |
more_categories = my_call_category_loads(); | |
printf("more_categories = %d\n", more_categories); | |
printf("loadable_classes_used = %d\n", loadable_classes_used); | |
//sleep(1); | |
}while(loadable_classes_used > 0 || more_categories); | |
//objc_autoreleasePoolPop(pool); | |
loading = NO; | |
puts(""); | |
} | |
int main (int argc, const char * argv[]){ | |
// Test with pseudo data | |
loadable_classes_used = 3; | |
loadable_categories_used = 5; | |
my_call_load_methods(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment