OSDN Git Service

referenceCountを導入。今のところ正常に動作している。メモリリークについても一部改善。69.67KB(1852/2023)>36.59KB(588/2163)
[chnosproject/CHNOSProject.git] / CHNOSProject / chn / chnlib00.c
index 7f3990a..f846051 100755 (executable)
@@ -26,6 +26,7 @@
 //Declare internal functions\r
 //\r
 CHNLIB_UIPArray *CHNLIB_UIPArray_Internal_Allocate(void);\r
+void CHNLIB_UIPArray_Internal_Destruct(void **structure);\r
 \r
 //\r
 //Define types\r
@@ -39,6 +40,7 @@ struct CHNLIB_UIPARRAY_INTERNAL_TAG {
 \r
 struct CHNLIB_UIPARRAY {\r
     //UnsignedIntとPointerを格納するArray構造体\r
+    //headerはすべてのpackにあるが、ReferenceCountはその特性上、先頭のものだけが有効である。\r
     CHNLIB_StructureHeader header;\r
     \r
     int using_tags;    //Number of using tags in this pack.\r
@@ -59,6 +61,7 @@ int CHNLIB_UIPArray_AppendLast(CHNLIB_UIPArray **array, uint data32, void *point
 {\r
     //戻り値:追加されたタグのIndex\r
     //Arrayの末尾にデータを追加する。\r
+    //追加された要素のpointerの参照先はArrayが所有する(Retain)\r
     int index;\r
     \r
     index = 0;\r
@@ -73,6 +76,8 @@ int CHNLIB_UIPArray_AppendLast(CHNLIB_UIPArray **array, uint data32, void *point
     (*array)->tag[(*array)->using_tags].pointer = pointer;\r
     (*array)->using_tags++;\r
     \r
+    CHNLIB_Retain(&pointer);\r
+    \r
     return index + (*array)->using_tags - 1;\r
 }\r
 \r
@@ -98,7 +103,7 @@ int CHNLIB_UIPArray_RemoveByIndex(CHNLIB_UIPArray **array, int index)
 {\r
     //戻り値:削除が成功したか(0:成功,-1:指定された添字の要素は存在しない)\r
     //indexが指し示す要素を削除し、後続の要素は前へつめる。\r
-    //å\89\8aé\99¤ã\81\95ã\82\8cã\81\9fè¦\81ç´ ã\81«æ ¼ç´\8dã\81\95ã\82\8cã\81¦ã\81\84ã\81\9fã\83\87ã\83¼ã\82¿ã\81«é\96¢ã\81\97ã\81¦ã\81¯é\96¢ç\9f¥ã\81\97ã\81ªã\81\84\r
+    //å\89\8aé\99¤ã\81\95ã\82\8cã\81\9fè¦\81ç´ ã\81®pointerã\81®å\8f\82ç\85§å\85\88ã\81®æ\89\80æ\9c\89ã\82\92æ\94¾æ£\84ã\81\99ã\82\8b(Release)\r
     int i;\r
     \r
     for(; (index / CHNLIB_UIPArray_INTERNAL_PACKDATAS) > 0; index -= CHNLIB_UIPArray_INTERNAL_PACKDATAS){\r
@@ -108,11 +113,17 @@ int CHNLIB_UIPArray_RemoveByIndex(CHNLIB_UIPArray **array, int index)
         array = &(*array)->next;\r
     }\r
     if(*array == NULL){\r
+        //大雑把に見て、配列の範囲外\r
         return -1;\r
     }\r
     if(index >= (*array)->using_tags){\r
+        //詳細に見て、一つのパックの中で、配列の範囲外\r
         return -1;\r
     }\r
+    \r
+    //参照先の所有を放棄\r
+    CHNLIB_Release(&(*array)->tag[index].pointer);\r
+    \r
     for(i = index; i < (*array)->using_tags - 1; i++){\r
         (*array)->tag[i] = (*array)->tag[i + 1];\r
     }\r
@@ -120,8 +131,8 @@ int CHNLIB_UIPArray_RemoveByIndex(CHNLIB_UIPArray **array, int index)
         if((*array)->next != NULL){\r
             if((*array)->using_tags != CHNLIB_UIPArray_INTERNAL_PACKDATAS || (*array)->next->using_tags == 0){\r
                 //タグ数とリンクの関係があわない。以下の状態になっている。\r
-                //次のパックがあるのに、間のパックが使い切られていない。\r
-                //次のパックがあるのに、次のパックに一つもデータがない。\r
+                //-次のパックがあるのに、間のパックが使い切られていない。\r
+                //-次のパックがあるのに、次のパックに一つもデータがない。\r
                 CHNLIB_ReportError("Internal data error.", CHNLIB_DEBUG_ARGUMENTS);\r
             }\r
             (*array)->tag[CHNLIB_UIPArray_INTERNAL_PACKDATAS - 1] = (*array)->next->tag[0];\r
@@ -311,7 +322,7 @@ CHNLIB_UIPArray *CHNLIB_UIPArray_CopyArray(const CHNLIB_UIPArray *source)
     return destination;\r
 }\r
 \r
-CHNLIB_UIPArray *CHNLIB_UIPArray_SortInDescendingOrderByData32(const CHNLIB_UIPArray *array)\r
+CHNLIB_UIPArray *CHNLIB_UIPArray_GetSortedInDescendingOrderByData32(const CHNLIB_UIPArray *array)\r
 {\r
     //タグをData32の値で降順(大きい方から小さい方)になるように整列した新たなArrayを返す。\r
     CHNLIB_UIPArray *sorted, *temp;\r
@@ -349,6 +360,8 @@ CHNLIB_UIPArray *CHNLIB_UIPArray_SortInDescendingOrderByData32(const CHNLIB_UIPA
         }\r
     }\r
     \r
+    release(temp);\r
+    \r
     return sorted;\r
 }\r
 \r
@@ -364,8 +377,43 @@ CHNLIB_UIPArray *CHNLIB_UIPArray_Internal_Allocate(void)
     tag = (CHNLIB_UIPArray *)CHNLIB_System_AllocateMemory_Strict(sizeof(CHNLIB_UIPArray), CHNLIB_DEBUG_ARGUMENTS);\r
     \r
     CHNLIB_StructureHeader_Initialize(&tag->header, CHNLIB_STRUCT_ID_UIPArray);\r
+    tag->header.destructor = &CHNLIB_UIPArray_Internal_Destruct;\r
     \r
     return tag;\r
 \r
 }\r
 \r
+void CHNLIB_UIPArray_Internal_Destruct(void **structure)\r
+{\r
+    //デストラクタ(実際にRelease->freeされる時に呼ばれる)\r
+    //方針:すべてのオブジェクトをReleaseした後、すべてのパックをFreeする。\r
+    int i;\r
+    CHNLIB_UIPArray *array;\r
+    \r
+    if(structure == NULL){\r
+        return;\r
+    }\r
+    if(CHNLIB_StructureHeader_GetTypeID(*structure) != CHNLIB_STRUCT_ID_UIPArray){\r
+        return;\r
+    }\r
+    \r
+#ifdef DEBUG_MEMORY_REFERENCE_COUNT\r
+    CHNLIB_Debug("Release(with free)[%p].", CHNLIB_DEBUG_ARGUMENTS, *structure);\r
+#endif\r
+    \r
+    array = *structure;\r
+    \r
+    for(; array != NULL; array = array->next){\r
+        for(i = 0; i < array->using_tags; i++){\r
+            if(array->tag[i].pointer != NULL){\r
+                CHNLIB_Release(&array->tag[i].pointer);\r
+            }\r
+        }\r
+    }\r
+\r
+    CHNLIB_UIPArray_FreeOnlyArray((CHNLIB_UIPArray **)structure);\r
+\r
+    return;\r
+}\r
+\r
+\r