OSDN Git Service

referenceCountを導入。今のところ正常に動作している。メモリリークについても一部改善。69.67KB(1852/2023)>36.59KB(588/2163)
[chnosproject/CHNOSProject.git] / CHNOSProject / chn / chnlib.c
index 781a107..7072ab9 100755 (executable)
@@ -95,6 +95,7 @@ void CHNLIB_StructureHeader_Initialize(CHNLIB_StructureHeader *header, uint type
 {\r
     //ライブラリ共通構造体ヘッダの初期化を行う。\r
     //各構造体のInitializeで呼ばれることを想定している。\r
+    //referenceCountは1で初期化される(初期化を行った関数が所有すると考える)\r
     if(header == NULL){\r
         CHNLIB_ReportError("Null structure.", CHNLIB_DEBUG_ARGUMENTS);\r
         return;\r
@@ -102,6 +103,11 @@ void CHNLIB_StructureHeader_Initialize(CHNLIB_StructureHeader *header, uint type
     \r
     header->signature = CHNLIB_STRUCTURE_SIGNATURE;\r
     header->typeid = typeid;\r
+#ifdef DEBUG_MEMORY_REFERENCE_COUNT\r
+    CHNLIB_Debug("Init with referenceCount = 1 [%p].", CHNLIB_DEBUG_ARGUMENTS, header);\r
+#endif\r
+    header->referenceCount = 1;\r
+    header->destructor = NULL;\r
     return;\r
 }\r
 \r
@@ -160,6 +166,83 @@ void CHNLIB_System_FreeMemory(void *p, const char filename[], int line, const ch
     return;\r
 }\r
 \r
+void CHNLIB_Retain(void **structure)\r
+{\r
+    //structureのreferenceCountをインクリメントする。\r
+    //referenceCountの初期値は1\r
+    \r
+    CHNLIB_StructureHeader *strhead;\r
+    \r
+    if(structure == NULL || *structure == NULL){\r
+        return;\r
+    }\r
+    \r
+    strhead = (CHNLIB_StructureHeader *)*structure;\r
+    if(strhead->signature == CHNLIB_STRUCTURE_SIGNATURE){\r
+#ifdef DEBUG_MEMORY_REFERENCE_COUNT\r
+        CHNLIB_Debug("Retain [%p].", CHNLIB_DEBUG_ARGUMENTS, *structure);\r
+#endif\r
+        strhead->referenceCount++;\r
+    }\r
+    \r
+    return;\r
+}\r
+\r
+void CHNLIB_Release(void **structure)\r
+{\r
+    //structureのreferenceCountをデクリメントする。\r
+    //デクリメントした結果referenceCount==0となった時、そのstructureを解放する。\r
+    //structureが内包しているオブジェクトについては、releaseを行う。\r
+    \r
+    CHNLIB_StructureHeader *strhead;\r
+    \r
+    if(structure == NULL || *structure == NULL){\r
+        return;\r
+    }\r
+    \r
+    strhead = (CHNLIB_StructureHeader *)*structure;\r
+    if(strhead->signature == CHNLIB_STRUCTURE_SIGNATURE){\r
+        if(strhead->referenceCount <= 1){\r
+            if(strhead->destructor == NULL){\r
+#ifdef DEBUG_MEMORY_REFERENCE_COUNT\r
+                CHNLIB_Debug("Release(with free)[%p].", CHNLIB_DEBUG_ARGUMENTS, *structure);\r
+#endif\r
+                free(*structure);\r
+            } else{\r
+                strhead->destructor(structure);\r
+            }\r
+        } else{\r
+#ifdef DEBUG_MEMORY_REFERENCE_COUNT\r
+            CHNLIB_Debug("Release[%p].", CHNLIB_DEBUG_ARGUMENTS, *structure);\r
+#endif\r
+            strhead->referenceCount--;\r
+            *structure = NULL;\r
+        }\r
+    }\r
+    \r
+    return;\r
+}\r
+\r
+void *CHNLIB_AutoRelease(void *structure)\r
+{\r
+    //structureのreferenceCountを、destructせずに0にする。\r
+    //オブジェクト確保後に自分の所有権を放棄して他の関数へ渡すときに利用する。\r
+    \r
+    CHNLIB_StructureHeader *strhead;\r
+    \r
+    if(structure != NULL){\r
+        strhead = (CHNLIB_StructureHeader *)structure;\r
+        if(strhead->signature == CHNLIB_STRUCTURE_SIGNATURE){\r
+#ifdef DEBUG_MEMORY_REFERENCE_COUNT\r
+            CHNLIB_Debug("Set AutoRelease [%p].", CHNLIB_DEBUG_ARGUMENTS, structure);\r
+#endif\r
+            strhead->referenceCount = 0;\r
+        }\r
+    }\r
+    \r
+    return structure;\r
+}\r
+\r
 //\r
 //Internal functions\r
 //\r