#include <Foundation/NSString.h>
#include <gperftools/heap-profiler.h>

//Class MLTestClass;

@interface MLTestClass: NSObject {
@public
}
- (id)init;
- (void)someF;
@end

@implementation MLTestClass
- (id)init
{
        return [super init];
}

- (void)someF
{
}

@end

static void ff(id obj, SEL _cmd)
{
//        fprintf(stderr, "we are here!!!!\n");
}

//static void deallocHiddenClass(id obj, SEL _cmd)
//{
//        fprintf(stderr, "we are here!!!!\n");
//}


int main()
{
        static char static_char;
        MLTestClass * tc;
        HeapProfilerStart("/tmp/test-prof");
        tc =  [[MLTestClass alloc] init];
        objc_setAssociatedObject(tc, &static_char, (id)1223, OBJC_ASSOCIATION_ASSIGN);
//        objc_setAssociatedObject(tc, &static_char, nil, OBJC_ASSOCIATION_ASSIGN);

        [tc release];
        
//        tc =  [[MLTestClass alloc] init];
//        [tc release];
        int i = 0;
        for (; i < 100000; ++i)
        {
                tc =  [[MLTestClass alloc] init];
//                [tc someF];

                objc_setAssociatedObject(tc, &static_char, (id)1223, OBJC_ASSOCIATION_ASSIGN);
	        static SEL some_sel = NULL;
	        static SEL destruct_sel = NULL;
                if (NULL == some_sel)
                {       
                    some_sel = sel_registerName(".some_sel");
                    destruct_sel = sel_registerName(".cxx_destruct");
                }
                const char *types = sizeof(void*) == 4 ? "v8@0:4" : "v16@0:8";
                class_addMethod(object_getClass(tc), some_sel,
                                (IMP)ff, types);
//                class_addMethod(object_getClass(tc), destruct_sel,
//                                (IMP)deallocHiddenClass, types);

//                fprintf(stderr, "respond? %s\n", (class_respondsToSelector(object_getClass(tc), destruct_sel) ? "YES"  : "NO"));
                [tc performSelector:some_sel];
                int j = (int)objc_getAssociatedObject(tc, &static_char); 
                fprintf(stderr, "i=%d\n" , j);
//                [tc someF];
//                objc_setAssociatedObject(tc, &static_char, tc, OBJC_ASSOCIATION_ASSIGN);
//                [tc someF];
//                objc_getAssociatedObject(tc, &static_char);
//                [tc finalize];
//		[tc cxx_destruct];
                [tc release];
        }
        HeapProfilerDump("by-req");
        HeapProfilerStop();
}
