浏览代码

[c] Optimized attachment lookup in skin. See #1117. (#1118)

* [c] Optimized attachment lookup in skin. See #1117.

* [c] Optimized attachment lookup in skin. See #1117. Changes according to suggestions in PR #1118.
Ievgen Mukhin 7 年之前
父节点
当前提交
cab8127626
共有 2 个文件被更改,包括 49 次插入5 次删除
  1. 11 1
      spine-c/spine-c/include/spine/Skin.h
  2. 38 4
      spine-c/spine-c/src/spine/Skin.c

+ 11 - 1
spine-c/spine-c/include/spine/Skin.h

@@ -38,6 +38,9 @@
 extern "C" {
 #endif
 
+/* Size of hashtable used in skin structure for fast attachment lookup. */
+#define SKIN_ENTRIES_HASH_TABLE_SIZE 100
+
 struct spSkeleton;
 
 typedef struct spSkin {
@@ -59,9 +62,16 @@ struct _Entry {
 	_Entry* next;
 };
 
+typedef struct _SkinHashTableEntry _SkinHashTableEntry;
+struct _SkinHashTableEntry {
+	_Entry* entry;
+	_SkinHashTableEntry* next;  /* list for elements with same hashes */
+};
+
 typedef struct {
 	spSkin super;
-	_Entry* entries;
+	_Entry* entries; /* entries list stored for getting attachment name by attachment index */
+	_SkinHashTableEntry* entriesHashTable[SKIN_ENTRIES_HASH_TABLE_SIZE];  /* hashtable for fast attachment lookup */
 } _spSkin;
 
 SP_API spSkin* spSkin_create (const char* name);

+ 38 - 4
spine-c/spine-c/src/spine/Skin.c

@@ -45,6 +45,16 @@ void _Entry_dispose (_Entry* self) {
 	FREE(self);
 }
 
+static _SkinHashTableEntry* _SkinHashTableEntry_create (_Entry* entry) {
+	_SkinHashTableEntry* self = NEW(_SkinHashTableEntry);
+	self->entry = entry;
+	return self;
+}
+
+static void _SkinHashTableEntry_dispose (_SkinHashTableEntry* self) {
+	FREE(self);
+}
+
 /**/
 
 spSkin* spSkin_create (const char* name) {
@@ -55,12 +65,28 @@ spSkin* spSkin_create (const char* name) {
 
 void spSkin_dispose (spSkin* self) {
 	_Entry* entry = SUB_CAST(_spSkin, self)->entries;
+
 	while (entry) {
 		_Entry* nextEntry = entry->next;
 		_Entry_dispose(entry);
 		entry = nextEntry;
 	}
 
+	{
+		_SkinHashTableEntry** currentHashtableEntry = SUB_CAST(_spSkin, self)->entriesHashTable;
+		int i;
+
+		for (i = 0; i < SKIN_ENTRIES_HASH_TABLE_SIZE; ++i, ++currentHashtableEntry) {
+			_SkinHashTableEntry* hashtableEntry = *currentHashtableEntry;
+
+			while (hashtableEntry) {
+				_SkinHashTableEntry* nextEntry = hashtableEntry->next;
+				_SkinHashTableEntry_dispose(hashtableEntry);
+				hashtableEntry = nextEntry;
+			}
+		}
+	}
+
 	FREE(self->name);
 	FREE(self);
 }
@@ -69,13 +95,21 @@ void spSkin_addAttachment (spSkin* self, int slotIndex, const char* name, spAtta
 	_Entry* newEntry = _Entry_create(slotIndex, name, attachment);
 	newEntry->next = SUB_CAST(_spSkin, self)->entries;
 	SUB_CAST(_spSkin, self)->entries = newEntry;
+
+	{
+		unsigned int hashTableIndex = (unsigned int)slotIndex % SKIN_ENTRIES_HASH_TABLE_SIZE;
+
+		_SkinHashTableEntry* newHashEntry = _SkinHashTableEntry_create(newEntry);
+		newHashEntry->next = SUB_CAST(_spSkin, self)->entriesHashTable[hashTableIndex];
+		SUB_CAST(_spSkin, self)->entriesHashTable[hashTableIndex] = newHashEntry;
+	}
 }
 
 spAttachment* spSkin_getAttachment (const spSkin* self, int slotIndex, const char* name) {
-	const _Entry* entry = SUB_CAST(_spSkin, self)->entries;
-	while (entry) {
-		if (entry->slotIndex == slotIndex && strcmp(entry->name, name) == 0) return entry->attachment;
-		entry = entry->next;
+	const _SkinHashTableEntry* hashEntry = SUB_CAST(_spSkin, self)->entriesHashTable[(unsigned int)slotIndex % SKIN_ENTRIES_HASH_TABLE_SIZE];
+	while (hashEntry) {
+		if (hashEntry->entry->slotIndex == slotIndex && strcmp(hashEntry->entry->name, name) == 0) return hashEntry->entry->attachment;
+		hashEntry = hashEntry->next;
 	}
 	return 0;
 }