Satoshi Nakagawa
snaka****@infot*****
Wed Jun 13 21:44:04 JST 2007
Hi. In [Rubycocoa-devel 939] parameters in callback are different from original objects [Rubycocoa-devel 890] NSObject.alloc.init doesn't return NSObject sometimes I reported the caching problem. In RubyKaigi 2007, Hisa-san and I talked about it, and I realized it is not solved fundamentally. I hit on a idea. We can clear cache when objects are being dealloc-ed. I have wrote a patch to implement it. It is a fundamental solution and works good for the problems I reported. But I don't have any idea where to insert the code. -- Satoshi Nakagawa Index: framework/src/objc/RBRuntime.m =================================================================== --- framework/src/objc/RBRuntime.m (revision 1837) +++ framework/src/objc/RBRuntime.m (working copy) @@ -228,6 +228,27 @@ return RBNotifyException(api_name, err); } + at implementation NSObject (__DeallocHook) +- (void)__clearCacheAndDealloc +{ + remove_from_oc2rb_cache(self); + [self __clearCacheAndDealloc]; +} + at end + +static void install_dealloc_hook() +{ + Method original_method, new_method; + IMP tmp; + + original_method = class_getInstanceMethod([NSObject class], @selector(dealloc)); + new_method = class_getInstanceMethod([NSObject class], @selector(__clearCacheAndDealloc)); + + tmp = original_method->method_imp; + original_method->method_imp = new_method->method_imp; + new_method->method_imp = tmp; +} + static int rubycocoa_initialized_flag = 0; static int rubycocoa_initialized_p() @@ -243,6 +264,7 @@ if (! rubycocoa_initialized_flag) { init_rb2oc_cache(); // initialize the Ruby->ObjC internal cache init_oc2rb_cache(); // initialize the ObjC->Ruby internal cache + install_dealloc_hook(); initialize_mdl_osxobjc(); // initialize an objc part of rubycocoa initialize_mdl_bundle_support(); init_ovmix(); Index: framework/src/objc/ocdata_conv.m =================================================================== --- framework/src/objc/ocdata_conv.m (revision 1837) +++ framework/src/objc/ocdata_conv.m (working copy) @@ -709,13 +709,11 @@ result = rbobj_get_ocid(context_obj) == ocid ? context_obj : ocobj_s_new(ocid); } - if (context_obj != Qfalse) { - CACHE_LOCK(&oc2rbCacheLock); - // Check out that the hash is still empty for us, to avoid a race condition. - if (!st_lookup(oc2rbCache, (st_data_t)ocid, (st_data_t *)&result)) - st_insert(oc2rbCache, (st_data_t)ocid, (st_data_t)result); - CACHE_UNLOCK(&oc2rbCacheLock); - } + CACHE_LOCK(&oc2rbCacheLock); + // Check out that the hash is still empty for us, to avoid a race condition. + if (!st_lookup(oc2rbCache, (st_data_t)ocid, (st_data_t *)&result)) + st_insert(oc2rbCache, (st_data_t)ocid, (st_data_t)result); + CACHE_UNLOCK(&oc2rbCacheLock); } return result;