diff options
author | Max Horn | 2009-05-04 15:23:33 +0000 |
---|---|---|
committer | Max Horn | 2009-05-04 15:23:33 +0000 |
commit | f2da4bc4477ade50f53753e8f7702e072ad3cf8c (patch) | |
tree | 90d8e587b4a94f4fdcc21229ac5445fd15b903b1 | |
parent | 27b74756d8039fe5aaed61bd4866087c64226faf (diff) | |
download | scummvm-rg350-f2da4bc4477ade50f53753e8f7702e072ad3cf8c.tar.gz scummvm-rg350-f2da4bc4477ade50f53753e8f7702e072ad3cf8c.tar.bz2 scummvm-rg350-f2da4bc4477ade50f53753e8f7702e072ad3cf8c.zip |
SCI: Got rid of heapmgr.h; further improve the Table code
svn-id: r40308
-rw-r--r-- | engines/sci/engine/heapmgr.h | 42 | ||||
-rw-r--r-- | engines/sci/engine/savegame.cpp | 4 | ||||
-rw-r--r-- | engines/sci/engine/seg_manager.cpp | 135 | ||||
-rw-r--r-- | engines/sci/engine/vm.h | 69 |
4 files changed, 105 insertions, 145 deletions
diff --git a/engines/sci/engine/heapmgr.h b/engines/sci/engine/heapmgr.h deleted file mode 100644 index f8975d428d..0000000000 --- a/engines/sci/engine/heapmgr.h +++ /dev/null @@ -1,42 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Heap-like managed structure */ - -#ifndef SCI_ENGINE_HEAPMGR_H -#define SCI_ENGINE_HEAPMGR_H - -namespace Sci { - -enum { HEAPENTRY_INVALID = -1 }; - -// FIXME: We write (i == 0 || i > 0) instead of (i >= 0) to silence certain annoying warnings: -// generated by GCC: "comparison is always true due to limited range of data type". -#define ENTRY_IS_VALID(t, i) ((i == 0 || i > 0) && (i) < (t)->max_entry && (t)->table[(i)].next_free == (i)) - - -} // End of namespace Sci - -#endif // SCI_ENGINE_HEAPMGR_H diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 4130671cc9..7741e802d2 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -551,13 +551,13 @@ static int clone_entry_used(CloneTable *table, int n) { int seeker = table->first_free; CloneTable::Entry *entries = table->table; - if (seeker == HEAPENTRY_INVALID) return 1; + if (seeker == CloneTable::HEAPENTRY_INVALID) return 1; do { if (seeker == n) return 0; backup = seeker; seeker = entries[seeker].next_free; - } while (entries[backup].next_free != HEAPENTRY_INVALID); + } while (entries[backup].next_free != CloneTable::HEAPENTRY_INVALID); return 1; } diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 460502827f..20470b8ebc 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -971,15 +971,80 @@ uint16 SegManager::validateExportFunc(int pubfunct, int seg) { return offset; } +template<typename T, int INITIAL, int INCREMENT> +Table<T, INITIAL, INCREMENT>::Table() { + entries_nr = 0; + max_entry = 0; + entries_used = 0; + first_free = HEAPENTRY_INVALID; + table = NULL; +} + +template<typename T, int INITIAL, int INCREMENT> +Table<T, INITIAL, INCREMENT>::~Table() { + // FIXME: Shouldn't we make sure that all table entries are disposed + // of properly? + free(table); + table = NULL; + entries_nr = max_entry = 0; +} + +template<typename T, int INITIAL, int INCREMENT> +void Table<T, INITIAL, INCREMENT>::initTable() { + entries_nr = INITIAL; + max_entry = 0; + entries_used = 0; + first_free = HEAPENTRY_INVALID; + table = (Entry *)calloc(INITIAL, sizeof(Entry)); +} + +template<typename T, int INITIAL, int INCREMENT> +int Table<T, INITIAL, INCREMENT>::allocEntry() { + entries_used++; + if (first_free != HEAPENTRY_INVALID) { + int oldff = first_free; + first_free = table[oldff].next_free; + + table[oldff].next_free = oldff; + return oldff; + } else { + if (max_entry == entries_nr) { + entries_nr += INCREMENT; + + table = (Entry *)sci_realloc(table, sizeof(Entry) * entries_nr); + memset(&table[entries_nr-INCREMENT], 0, INCREMENT * sizeof(Entry)); + } + table[max_entry].next_free = max_entry; /* Tag as 'valid' */ + return max_entry++; + } +} + +template<typename T, int INITIAL, int INCREMENT> +void Table<T, INITIAL, INCREMENT>::freeEntry(int idx) { + if (idx < 0 || idx >= max_entry) { + error("Table::freeEntry: Attempt to release invalid table index %d", idx); + } + + table[idx].next_free = first_free; + first_free = idx; + entries_used--; +} + +template<typename T, int INITIAL, int INCREMENT> +bool Table<T, INITIAL, INCREMENT>::isValidEntry(int idx) { + return idx >= 0 && idx < max_entry && table[idx].next_free == idx; +} + + void SegManager::free_hunk_entry(reg_t addr) { - MemObject *mobj = GET_SEGMENT(*this, addr.segment, MEM_OBJ_HUNK); + HunkTable *ht = (HunkTable *)GET_SEGMENT(*this, addr.segment, MEM_OBJ_HUNK); - if (!mobj) { + if (!ht) { sciprintf("Attempt to free Hunk from address "PREG": Invalid segment type\n", PRINT_REG(addr)); return; } - Sci::free_Hunk_entry((HunkTable *)mobj, addr.offset); + ht->freeEntry(addr.offset); } Hunk *SegManager::alloc_hunk_entry(const char *hunk_type, int size, reg_t *reg) { @@ -995,53 +1060,6 @@ Hunk *SegManager::alloc_hunk_entry(const char *hunk_type, int size, reg_t *reg) return h; } - -void free_List_entry(ListTable *table, int index) { - if (index < 0 || index >= table->max_entry) { - error("heapmgr: Attempt to release invalid table index %d", index); - } - - table->table[index].next_free = table->first_free; - table->first_free = index; - table->entries_used--; -} - -void free_Node_entry(NodeTable *table, int index) { - if (index < 0 || index >= table->max_entry) { - error("heapmgr: Attempt to release invalid table index %d", index); - } - - table->table[index].next_free = table->first_free; - table->first_free = index; - table->entries_used--; -} - -void free_Clone_entry(CloneTable *table, int index) { - if (index < 0 || index >= table->max_entry) { - error("heapmgr: Attempt to release invalid table index %d", index); - } - - free(table->table[index].variables); // Free the dynamically allocated memory part - - table->table[index].next_free = table->first_free; - table->first_free = index; - table->entries_used--; -} - -void free_Hunk_entry(HunkTable *table, int index) { - if (index < 0 || index >= table->max_entry) { - error("heapmgr: Attempt to release invalid table index %d", index); - } - - free(table->table[index].mem); - - table->table[index].next_free = table->first_free; - table->first_free = index; - table->entries_used--; -} - - - Clone *SegManager::alloc_Clone(reg_t *addr) { CloneTable *table; int offset; @@ -1354,11 +1372,12 @@ void SegInterfaceClones::listAllOutgoingReferences(EngineState *s, reg_t addr, v } void SegInterfaceClones::freeAtAddress(reg_t addr) { + CloneTable *clone_table = (CloneTable *)_mobj; Object *victim_obj; assert(addr.segment == _segId); - victim_obj = &((*(CloneTable *)_mobj).table[addr.offset]); + victim_obj = &(clone_table->table[addr.offset]); #ifdef GC_DEBUG if (!(victim_obj->flags & OBJECT_FLAG_FREED)) @@ -1374,7 +1393,7 @@ void SegInterfaceClones::freeAtAddress(reg_t addr) { */ free(victim_obj->variables); victim_obj->variables = NULL; - Sci::free_Clone_entry((CloneTable *)_mobj, addr.offset); + clone_table->freeEntry(addr.offset); } @@ -1463,7 +1482,8 @@ public: }; void SegInterfaceLists::freeAtAddress(reg_t sub_addr) { - Sci::free_List_entry((ListTable *)_mobj, sub_addr.offset); + ListTable *table = (ListTable *)_mobj; + table->freeEntry(sub_addr.offset); } void SegInterfaceLists::listAllDeallocatable(void *param, NoteCallback note) { @@ -1471,8 +1491,6 @@ void SegInterfaceLists::listAllDeallocatable(void *param, NoteCallback note) { for (int i = 0; i < table->max_entry; i++) if (ENTRY_IS_VALID(table, i)) (*note) (param, make_reg(_segId, i)); - - } void SegInterfaceLists::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { @@ -1502,7 +1520,8 @@ public: }; void SegInterfaceNodes::freeAtAddress(reg_t sub_addr) { - Sci::free_Node_entry((NodeTable *)_mobj, sub_addr.offset); + NodeTable *table = (NodeTable *)_mobj; + table->freeEntry(sub_addr.offset); } void SegInterfaceNodes::listAllDeallocatable(void *param, NoteCallback note) { @@ -1510,8 +1529,6 @@ void SegInterfaceNodes::listAllDeallocatable(void *param, NoteCallback note) { for (int i = 0; i < table->max_entry; i++) if (ENTRY_IS_VALID(table, i)) (*note) (param, make_reg(_segId, i)); - - } void SegInterfaceNodes::listAllOutgoingReferences(EngineState *s, reg_t addr, void *param, NoteCallback note) { @@ -1551,8 +1568,6 @@ void SegInterfaceHunk::listAllDeallocatable(void *param, NoteCallback note) { for (int i = 0; i < table->max_entry; i++) if (ENTRY_IS_VALID(table, i)) (*note) (param, make_reg(_segId, i)); - - } diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 791601015d..49422f23d5 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -31,7 +31,6 @@ //#include "common/serializer.h" #include "sci/scicore/versions.h" // for sci_version_t #include "sci/engine/vm_types.h" // for reg_t -#include "sci/engine/heapmgr.h" namespace Sci { @@ -398,6 +397,8 @@ struct Table : public MemObject { struct Entry : public T { int next_free; /* Only used for free entries */ }; + enum { HEAPENTRY_INVALID = -1 }; + int entries_nr; /**< Number of entries allocated */ int first_free; /**< Beginning of a singly linked list for entries */ @@ -407,63 +408,49 @@ struct Table : public MemObject { Entry *table; public: - ~Table() { - // FIXME: Shouldn't we make sure that all table entries are disposed - // of properly? - free(table); - table = NULL; - entries_nr = max_entry = 0; - } + Table(); + ~Table(); + + void initTable(); + int allocEntry(); + bool isValidEntry(int idx); + virtual void freeEntry(int idx); // virtual void saveLoadWithSerializer(Common::Serializer &ser); +}; - void initTable() { - entries_nr = INITIAL; - max_entry = 0; - entries_used = 0; - first_free = HEAPENTRY_INVALID; - table = (Entry *)calloc(INITIAL, sizeof(Entry)); - } +// FIXME: Replace ENTRY_IS_VALID by a direct method call +#define ENTRY_IS_VALID(t, i) ((t)->isValidEntry(i)) - int allocEntry() { - entries_used++; - if (first_free != HEAPENTRY_INVALID) { - int oldff = first_free; - first_free = table[oldff].next_free; - table[oldff].next_free = oldff; - return oldff; - } else { - if (max_entry == entries_nr) { - entries_nr += INCREMENT; +/* CloneTable */ +struct CloneTable : public Table<Clone, 16, 4> { + virtual void freeEntry(int idx) { + Table<Clone, 16, 4>::freeEntry(idx); - table = (Entry *)sci_realloc(table, sizeof(Entry) * entries_nr); - memset(&table[entries_nr-INCREMENT], 0, INCREMENT * sizeof(Entry)); - } - table[max_entry].next_free = max_entry; /* Tag as 'valid' */ - return max_entry++; - } + free(table[idx].variables); // Free the dynamically allocated memory part } }; -/* CloneTable */ -typedef Table<Clone, 16, 4> CloneTable; -void free_Clone_entry(CloneTable *table, int index); - /* NodeTable */ -typedef Table<Node, 32, 16> NodeTable; -void free_Node_entry(NodeTable *table, int index); +struct NodeTable : public Table<Node, 32, 16> { +}; /* ListTable */ -typedef Table<List, 8, 4> ListTable; -void free_List_entry(ListTable *table, int index); +struct ListTable : public Table<List, 8, 4> { +}; /* HunkTable */ -typedef Table<Hunk, 4, 4> HunkTable; -void free_Hunk_entry(HunkTable *table, int index); +struct HunkTable : public Table<Hunk, 4, 4> { + virtual void freeEntry(int idx) { + Table<Hunk, 4, 4>::freeEntry(idx); + + free(table[idx].mem); + } +}; // Free-style memory |