[macruby-changes] [217] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Sun May 25 01:25:09 PDT 2008


Revision: 217
          http://trac.macosforge.org/projects/ruby/changeset/217
Author:   lsansonetti at apple.com
Date:     2008-05-25 01:25:09 -0700 (Sun, 25 May 2008)

Log Message:
-----------
implemented ObjectSpace finalizers, make sure irb reads /etc/irbrc (#59)

Modified Paths:
--------------
    MacRuby/trunk/gc.c
    MacRuby/trunk/include/ruby/intern.h
    MacRuby/trunk/lib/irb/init.rb
    MacRuby/trunk/objc.m
    MacRuby/trunk/variable.c

Modified: MacRuby/trunk/gc.c
===================================================================
--- MacRuby/trunk/gc.c	2008-05-24 07:55:26 UTC (rev 216)
+++ MacRuby/trunk/gc.c	2008-05-25 08:25:09 UTC (rev 217)
@@ -2397,11 +2397,23 @@
  *
  */
 
+#if WITH_OBJC
+static CFMutableDictionaryRef __os_finalizers = NULL;
+#endif
+
 static VALUE
 undefine_final(VALUE os, VALUE obj)
 {
 #if WITH_OBJC
-    rb_notimplement();
+    if (__os_finalizers != NULL)
+	CFDictionaryRemoveValue(__os_finalizers, (const void *)obj);
+    
+    if (rb_objc_is_non_native(obj)) {
+	rb_objc_flag_set(obj, FL_FINALIZE, false);
+    }
+    else {
+	FL_UNSET(obj, FL_FINALIZE);
+    }
 #else
     rb_objspace_t *objspace = &rb_objspace;
     if (finalizer_table) {
@@ -2424,7 +2436,38 @@
 define_final(int argc, VALUE *argv, VALUE os)
 {
 #if WITH_OBJC
-    rb_notimplement();
+    VALUE obj, block, table;
+
+    if (__os_finalizers == NULL)
+	__os_finalizers = CFDictionaryCreateMutable(NULL, 0, NULL,
+	    &kCFTypeDictionaryValueCallBacks);
+
+    rb_scan_args(argc, argv, "11", &obj, &block);
+    if (argc == 1) {
+	block = rb_block_proc();
+    }
+    else if (!rb_respond_to(block, rb_intern("call"))) {
+	rb_raise(rb_eArgError, "wrong type argument %s (should be callable)",
+		 rb_obj_classname(block));
+    }
+
+    table = (VALUE)CFDictionaryGetValue((CFDictionaryRef)__os_finalizers, 
+	(const void *)obj);
+
+    if (table == 0) {
+	table = rb_ary_new();
+	CFDictionarySetValue(__os_finalizers, (const void *)obj, 
+	    (const void *)table);
+    }
+
+    rb_ary_push(table, block);
+    
+    if (rb_objc_is_non_native(obj)) {
+	rb_objc_flag_set(obj, FL_FINALIZE, true);
+    }
+    else {
+	FL_SET(obj, FL_FINALIZE);
+    }
 #else
     rb_objspace_t *objspace = &rb_objspace;
     VALUE obj, block, table;
@@ -2459,7 +2502,30 @@
 rb_gc_copy_finalizer(VALUE dest, VALUE obj)
 {
 #if WITH_OBJC
-    /* TODO */
+    VALUE table;
+
+    if (__os_finalizers == NULL)
+	return;
+
+    if (rb_objc_is_non_native(obj)) {
+	if (!rb_objc_flag_check(obj, FL_FINALIZE))
+	    return;
+    }
+    else {
+	if (!FL_TEST(obj, FL_FINALIZE))
+	    return;
+    }
+
+    table = (VALUE)CFDictionaryGetValue((CFDictionaryRef)__os_finalizers,
+	(const void *)obj);
+
+    if (table == 0) {
+	CFDictionaryRemoveValue(__os_finalizers, (const void *)dest);
+    }
+    else {
+	CFDictionarySetValue(__os_finalizers, (const void *)dest, 
+	    (const void *)table);	
+    }
 #else
     rb_objspace_t *objspace = &rb_objspace;
     VALUE table;
@@ -2533,6 +2599,14 @@
     CFArrayAppendValue(__exit_finalize, (void *)v);
 }
 
+static void rb_call_os_finalizer2(VALUE, VALUE);
+
+static void
+os_finalize_cb(const void *key, const void *val, void *context)
+{
+    rb_call_os_finalizer2((VALUE)key, (VALUE)val);
+}
+
 void
 rb_gc_call_finalizer_at_exit(void)
 {
@@ -2545,9 +2619,17 @@
 	    v = (VALUE)CFArrayGetValueAtIndex((CFArrayRef)__exit_finalize, i);
 	    rb_objc_finalize_pure_ruby_obj(v);
 	}
+	CFArrayRemoveAllValues(__exit_finalize);
+	CFRelease(__exit_finalize);
     }
-    CFArrayRemoveAllValues(__exit_finalize);
-    CFRelease(__exit_finalize);
+
+    if (__os_finalizers != NULL) {
+	CFDictionaryApplyFunction((CFDictionaryRef)__os_finalizers,
+    	    os_finalize_cb, NULL);
+	CFDictionaryRemoveAllValues(__os_finalizers);
+	CFRelease(__os_finalizers);
+    }
+
     auto_collect(__auto_zone, AUTO_COLLECT_FULL_COLLECTION, NULL);
 }
 
@@ -2917,20 +2999,71 @@
 static void (*old_batch_invalidate)(auto_zone_t *, 
     auto_zone_foreach_object_t, auto_zone_cursor_t, size_t);
 
+static VALUE
+run_single_final(VALUE arg)
+{
+    VALUE *args = (VALUE *)arg;
+    rb_eval_cmd(args[0], args[1], (int)args[2]);
+    return Qnil;
+}
+
 static void
+rb_call_os_finalizer2(VALUE obj, VALUE table)
+{
+    long i, count;
+    VALUE args[3];
+    int status, critical_save;
+
+    critical_save = rb_thread_critical;
+    rb_thread_critical = Qtrue;
+
+    args[1] = rb_ary_new3(1, rb_obj_id(obj));
+    args[2] = (VALUE)rb_safe_level();
+
+    for (i = 0, count = RARRAY_LEN(table); i < count; i++) {
+	args[0] = RARRAY_AT(table, i);
+	rb_protect(run_single_final, (VALUE)args, &status);
+    }
+
+    rb_thread_critical = critical_save;
+}
+
+static void
+rb_call_os_finalizer(void *obj)
+{
+    if (__os_finalizers != NULL) {
+	VALUE table;
+
+	table = (VALUE)CFDictionaryGetValue((CFDictionaryRef)__os_finalizers,
+	    (const void *)obj);
+
+	if (table != 0) {
+	    rb_call_os_finalizer2((VALUE)obj, table);
+	    CFDictionaryRemoveValue(__os_finalizers, (const void *)obj);
+	}
+    }
+}
+
+static void
 __rb_objc_finalize(void *obj, void *data)
 {
     if (rb_objc_is_non_native((VALUE)obj)) {
 	static SEL sel = NULL;
-	rb_objc_remove_keys(obj);
-	rb_free_generic_ivar((VALUE)obj, true);
+	long flag;
+	flag = rb_objc_remove_flags(obj);
+	if ((flag & FL_FINALIZE) == FL_FINALIZE)
+	    rb_call_os_finalizer(obj);
+	if ((flag & FL_EXIVAR) == FL_EXIVAR)
+	    rb_free_generic_ivar((VALUE)obj);
 	if (sel == NULL)
 	    sel = sel_registerName("finalize");
 	objc_msgSend(obj, sel);
     }
     else {
+	if (FL_TEST(obj, FL_FINALIZE))
+	    rb_call_os_finalizer(obj);
 	if (FL_TEST(obj, FL_EXIVAR))
-	    rb_free_generic_ivar((VALUE)obj, false);
+	    rb_free_generic_ivar((VALUE)obj);
     }
 }
 

Modified: MacRuby/trunk/include/ruby/intern.h
===================================================================
--- MacRuby/trunk/include/ruby/intern.h	2008-05-24 07:55:26 UTC (rev 216)
+++ MacRuby/trunk/include/ruby/intern.h	2008-05-25 08:25:09 UTC (rev 217)
@@ -656,7 +656,7 @@
 void rb_copy_generic_ivar(VALUE,VALUE);
 void rb_mark_generic_ivar(VALUE);
 void rb_mark_generic_ivar_tbl(void);
-void rb_free_generic_ivar(VALUE,bool);
+void rb_free_generic_ivar(VALUE);
 VALUE rb_ivar_get(VALUE, ID);
 VALUE rb_ivar_set(VALUE, ID, VALUE);
 VALUE rb_ivar_defined(VALUE, ID);

Modified: MacRuby/trunk/lib/irb/init.rb
===================================================================
--- MacRuby/trunk/lib/irb/init.rb	2008-05-24 07:55:26 UTC (rev 216)
+++ MacRuby/trunk/lib/irb/init.rb	2008-05-25 08:25:09 UTC (rev 217)
@@ -240,6 +240,7 @@
     yield proc{|rc| home+"/irb#{rc.sub(/\A_?/, '.')}"}
     yield proc{|rc| home+"/_irb#{rc}"}
     yield proc{|rc| home+"/$irb#{rc}"}
+    yield proc{|rc| "/etc/irb#{rc}"}
   end
 
   # loading modules

Modified: MacRuby/trunk/objc.m
===================================================================
--- MacRuby/trunk/objc.m	2008-05-24 07:55:26 UTC (rev 216)
+++ MacRuby/trunk/objc.m	2008-05-25 08:25:09 UTC (rev 217)
@@ -2661,10 +2661,16 @@
     CFDictionarySetValue(__obj_flags, obj, (void *)v);
 }
 
-void
-rb_objc_remove_keys(const void *obj)
+long
+rb_objc_remove_flags(const void *obj)
 {
-    CFDictionaryRemoveValue(__obj_flags, obj);
+    long flag;
+    if (CFDictionaryGetValueIfPresent(__obj_flags, obj, 
+	(const void **)&flag)) {
+	CFDictionaryRemoveValue(__obj_flags, obj);
+	return flag;
+    }
+    return 0;
 }
 
 static void
@@ -2914,3 +2920,13 @@
 	CFRunLoopAddTimer(CFRunLoopGetMain(), timer, kCFRunLoopDefaultMode);
     }
 }
+
+ at interface Protocol
+ at end
+
+ at implementation Protocol (MRFindProtocol)
++(id)protocolWithName:(NSString *)name
+{
+    return (id)objc_getProtocol([name UTF8String]);
+} 
+ at end

Modified: MacRuby/trunk/variable.c
===================================================================
--- MacRuby/trunk/variable.c	2008-05-24 07:55:26 UTC (rev 216)
+++ MacRuby/trunk/variable.c	2008-05-25 08:25:09 UTC (rev 217)
@@ -844,7 +844,7 @@
 }
 
 static void
-generic_ivar_set(VALUE obj, ID id, VALUE val, int pure)
+generic_ivar_set(VALUE obj, ID id, VALUE val)
 {
 #if WITH_OBJC
     CFMutableDictionaryRef obj_dict;
@@ -879,8 +879,6 @@
 	    (const void *)obj_dict);
 	CFMakeCollectable(obj_dict);
     }
-    if (!pure)
-	FL_SET(obj, FL_EXIVAR);
     CFDictionarySetValue(obj_dict, (const void *)id, (const void *)val);
 #else
     st_table *tbl;
@@ -1012,21 +1010,11 @@
 #endif
 
 void
-rb_free_generic_ivar(VALUE obj, bool lookup)
+rb_free_generic_ivar(VALUE obj)
 {
 #if WITH_OBJC
-    if (generic_iv_dict != NULL) {
-	if (lookup) {
-	    if (CFDictionaryGetValueIfPresent(generic_iv_dict, 
-		(const void *)obj, NULL)) {
-		CFDictionaryReplaceValue(generic_iv_dict, (const void *)obj, 
-		    NULL);
-	    }
-	}
-	else {
-	    CFDictionaryRemoveValue(generic_iv_dict, (const void *)obj);
-	}
-    }
+    if (generic_iv_dict != NULL)
+	CFDictionaryRemoveValue(generic_iv_dict, (const void *)obj);
 #else
     st_data_t tbl;
 
@@ -1157,7 +1145,8 @@
     if (OBJ_FROZEN(obj)) rb_error_frozen("object");
 #if WITH_OBJC
     if (rb_objc_is_non_native(obj)) {
-	generic_ivar_set(obj, id, val, 1);
+	rb_objc_flag_set(obj, FL_EXIVAR, true);
+	generic_ivar_set(obj, id, val);
 	return val;
     }
 #endif
@@ -1221,7 +1210,8 @@
 	st_insert(RCLASS_IV_TBL(obj), id, val);
         break;
       default:
-	generic_ivar_set(obj, id, val, 0);
+	generic_ivar_set(obj, id, val);
+	FL_SET(obj, FL_EXIVAR);
 	break;
     }
     return val;
@@ -1316,9 +1306,11 @@
     if (generic_iv_dict != NULL) {
 	CFDictionaryRef obj_dict;
 
-	obj_dict = (CFDictionaryRef)CFDictionaryGetValue((CFDictionaryRef)generic_iv_dict, (const void *)obj);
+	obj_dict = (CFDictionaryRef)CFDictionaryGetValue(
+	    (CFDictionaryRef)generic_iv_dict, (const void *)obj);
 	if (obj_dict != NULL)
-	    CFDictionaryApplyFunction(obj_dict, (CFDictionaryApplierFunction)func, (void *)arg);
+	    CFDictionaryApplyFunction(obj_dict, 
+		(CFDictionaryApplierFunction)func, (void *)arg);
     }
 #else
     if (!generic_iv_tbl) break;

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/macruby-changes/attachments/20080525/6264dcf2/attachment.htm 


More information about the macruby-changes mailing list