mirror of
https://github.com/holub/mame
synced 2025-06-04 20:06:28 +03:00
tagged_list without tagmap_t (nw)
This commit is contained in:
parent
e883c98c93
commit
9a2ed1703a
@ -86,7 +86,6 @@ project "utils"
|
||||
MAME_DIR .. "src/lib/util/pool.h",
|
||||
MAME_DIR .. "src/lib/util/sha1.cpp",
|
||||
MAME_DIR .. "src/lib/util/sha1.h",
|
||||
MAME_DIR .. "src/lib/util/tagmap.cpp",
|
||||
MAME_DIR .. "src/lib/util/tagmap.h",
|
||||
MAME_DIR .. "src/lib/util/unicode.cpp",
|
||||
MAME_DIR .. "src/lib/util/unicode.h",
|
||||
|
@ -354,11 +354,6 @@ int running_machine::run(bool firstrun)
|
||||
// perform a soft reset -- this takes us to the running phase
|
||||
soft_reset();
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
g_tagmap_finds = 0;
|
||||
if (strcmp(config().m_gamedrv.name, "___empty") != 0)
|
||||
g_tagmap_counter_enabled = true;
|
||||
#endif
|
||||
// handle initial load
|
||||
if (m_saveload_schedule != SLS_NONE)
|
||||
handle_saveload();
|
||||
@ -392,15 +387,6 @@ int running_machine::run(bool firstrun)
|
||||
// and out via the exit phase
|
||||
m_current_phase = MACHINE_PHASE_EXIT;
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
if (g_tagmap_counter_enabled)
|
||||
{
|
||||
g_tagmap_counter_enabled = false;
|
||||
if (*(options().command()) == 0)
|
||||
osd_printf_info("%d tagmap lookups\n", g_tagmap_finds);
|
||||
}
|
||||
#endif
|
||||
|
||||
// save the NVRAM and configuration
|
||||
sound().ui_mute(true);
|
||||
nvram_save();
|
||||
@ -443,15 +429,6 @@ int running_machine::run(bool firstrun)
|
||||
// in case we got here via exception
|
||||
m_current_phase = MACHINE_PHASE_EXIT;
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
if (g_tagmap_counter_enabled)
|
||||
{
|
||||
g_tagmap_counter_enabled = false;
|
||||
if (*(options().command()) == 0)
|
||||
osd_printf_info("%d tagmap lookups\n", g_tagmap_finds);
|
||||
}
|
||||
#endif
|
||||
|
||||
// call all exit callbacks registered
|
||||
call_notifiers(MACHINE_NOTIFY_EXIT);
|
||||
zip_file_cache_clear();
|
||||
@ -473,15 +450,6 @@ void running_machine::schedule_exit()
|
||||
// if we're executing, abort out immediately
|
||||
m_scheduler.eat_all_cycles();
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
if (g_tagmap_counter_enabled)
|
||||
{
|
||||
g_tagmap_counter_enabled = false;
|
||||
if (*(options().command()) == 0)
|
||||
osd_printf_info("%d tagmap lookups\n", g_tagmap_finds);
|
||||
}
|
||||
#endif
|
||||
|
||||
// if we're autosaving on exit, schedule a save as well
|
||||
if (options().autosave() && (m_system.flags & MACHINE_SUPPORTS_SAVE) && this->time() > attotime::zero)
|
||||
schedule_save("auto");
|
||||
|
@ -1037,15 +1037,6 @@ void video_manager::recompute_speed(const attotime &emutime)
|
||||
// if we're past the "time-to-execute" requested, signal an exit
|
||||
if (m_seconds_to_run != 0 && emutime.seconds() >= m_seconds_to_run)
|
||||
{
|
||||
#ifdef MAME_DEBUG
|
||||
if (g_tagmap_counter_enabled)
|
||||
{
|
||||
g_tagmap_counter_enabled = false;
|
||||
if (*(machine().options().command()) == 0)
|
||||
osd_printf_info("%d tagmap lookups\n", g_tagmap_finds);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (machine().first_screen() != nullptr)
|
||||
{
|
||||
// create a final screenshot
|
||||
|
@ -1,20 +0,0 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Aaron Giles
|
||||
/***************************************************************************
|
||||
|
||||
tagmap.c
|
||||
|
||||
tagmap counter
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "tagmap.h"
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
/** @brief The tagmap finds. */
|
||||
INT32 g_tagmap_finds = 0;
|
||||
/** @brief true to enable, false to disable the tagmap counter. */
|
||||
bool g_tagmap_counter_enabled = false;
|
||||
#endif
|
@ -17,11 +17,7 @@
|
||||
#include "coretmpl.h"
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#ifdef MAME_DEBUG
|
||||
#include "eminline.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
//**************************************************************************
|
||||
// CONSTANTS
|
||||
@ -33,169 +29,6 @@ enum tagmap_error
|
||||
TMERR_DUPLICATE
|
||||
};
|
||||
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
extern INT32 g_tagmap_finds;
|
||||
extern bool g_tagmap_counter_enabled;
|
||||
#endif
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// generally used for small tables, though the hash size can be increased
|
||||
// as necessary; good primes are: 53, 97, 193, 389, 769, 1543, 3079, 6151, etc
|
||||
template<class _ElementType, int _HashSize = 53>
|
||||
class tagmap_t
|
||||
{
|
||||
private:
|
||||
// disable copying/assignment
|
||||
tagmap_t(const tagmap_t &);
|
||||
tagmap_t &operator=(const tagmap_t &);
|
||||
|
||||
public:
|
||||
// an entry in the table
|
||||
class entry_t
|
||||
{
|
||||
friend class tagmap_t<_ElementType, _HashSize>;
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
entry_t(const char *tag, UINT32 fullhash, _ElementType object)
|
||||
: m_next(nullptr),
|
||||
m_fullhash(fullhash),
|
||||
m_tag(tag),
|
||||
m_object(std::move(object)) { }
|
||||
|
||||
// accessors
|
||||
const std::string &tag() const { return m_tag; }
|
||||
_ElementType object() const { return m_object; }
|
||||
|
||||
// setters
|
||||
void set_object(_ElementType object) { m_object = object; }
|
||||
|
||||
private:
|
||||
// internal helpers
|
||||
entry_t *next() const { return m_next; }
|
||||
UINT32 fullhash() const { return m_fullhash; }
|
||||
|
||||
// internal state
|
||||
entry_t * m_next;
|
||||
UINT32 m_fullhash;
|
||||
std::string m_tag;
|
||||
_ElementType m_object;
|
||||
};
|
||||
|
||||
// construction/destruction
|
||||
tagmap_t() { memset(m_table, 0, sizeof(m_table)); }
|
||||
~tagmap_t() { reset(); }
|
||||
|
||||
// core hashing function
|
||||
UINT32 hash(const char *string) const
|
||||
{
|
||||
UINT32 result = *string++;
|
||||
for (UINT8 c = *string++; c != 0; c = *string++)
|
||||
result = (result*33) ^ c;
|
||||
return result;
|
||||
}
|
||||
|
||||
// empty the list
|
||||
void reset()
|
||||
{
|
||||
for (auto & elem : m_table)
|
||||
while (elem != nullptr)
|
||||
remove_common(&elem);
|
||||
}
|
||||
|
||||
// add/remove
|
||||
tagmap_error add(const char *tag, _ElementType object, bool replace_if_duplicate = false) { return add_common(tag, object, replace_if_duplicate, false); }
|
||||
tagmap_error add_unique_hash(const char *tag, _ElementType object, bool replace_if_duplicate = false) { return add_common(tag, object, replace_if_duplicate, true); }
|
||||
|
||||
// remove by tag
|
||||
void remove(const char *tag)
|
||||
{
|
||||
UINT32 fullhash = hash(tag);
|
||||
for (entry_t **entryptr = &m_table[fullhash % ARRAY_LENGTH(m_table)]; *entryptr != nullptr; entryptr = &(*entryptr)->m_next)
|
||||
if ((*entryptr)->fullhash() == fullhash && (*entryptr)->tag() == tag)
|
||||
return remove_common(entryptr);
|
||||
}
|
||||
|
||||
// remove by object
|
||||
void remove(_ElementType object)
|
||||
{
|
||||
for (auto & elem : m_table)
|
||||
for (entry_t **entryptr = &elem; *entryptr != nullptr; entryptr = &(*entryptr)->m_next)
|
||||
if ((*entryptr)->object() == object)
|
||||
return remove_common(entryptr);
|
||||
}
|
||||
|
||||
// find by tag
|
||||
_ElementType find(const char *tag) const { return find(tag, hash(tag)); }
|
||||
|
||||
// find by tag with precomputed hash
|
||||
_ElementType find(const char *tag, UINT32 fullhash) const
|
||||
{
|
||||
#ifdef MAME_DEBUG
|
||||
if (g_tagmap_counter_enabled)
|
||||
atomic_increment32(&g_tagmap_finds);
|
||||
#endif
|
||||
for (entry_t *entry = m_table[fullhash % ARRAY_LENGTH(m_table)]; entry != nullptr; entry = entry->next())
|
||||
if (entry->fullhash() == fullhash && entry->tag() == tag)
|
||||
return entry->object();
|
||||
return _ElementType(NULL);
|
||||
}
|
||||
|
||||
// find by tag without checking anything but the hash
|
||||
_ElementType find_hash_only(const char *tag) const
|
||||
{
|
||||
#ifdef MAME_DEBUG
|
||||
if (g_tagmap_counter_enabled)
|
||||
atomic_increment32(&g_tagmap_finds);
|
||||
#endif
|
||||
UINT32 fullhash = hash(tag);
|
||||
for (entry_t *entry = m_table[fullhash % ARRAY_LENGTH(m_table)]; entry != nullptr; entry = entry->next())
|
||||
if (entry->fullhash() == fullhash)
|
||||
return entry->object();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// return first object in the table
|
||||
entry_t *first() const { return next(NULL); }
|
||||
|
||||
// return next object in the table
|
||||
entry_t *next(entry_t *after) const
|
||||
{
|
||||
// if there's another item in this hash bucket, just return it
|
||||
if (after != NULL && after->next() != NULL)
|
||||
return after->next();
|
||||
|
||||
// otherwise scan forward for the next bucket with an entry
|
||||
UINT32 firstindex = (after != NULL) ? (after->fullhash() % ARRAY_LENGTH(m_table) + 1) : 0;
|
||||
for (UINT32 hashindex = firstindex; hashindex < ARRAY_LENGTH(m_table); hashindex++)
|
||||
if (m_table[hashindex] != NULL)
|
||||
return m_table[hashindex];
|
||||
|
||||
// all out
|
||||
return NULL;
|
||||
}
|
||||
|
||||
private:
|
||||
// internal helpers
|
||||
tagmap_error add_common(const char *tag, _ElementType object, bool replace_if_duplicate, bool unique_hash);
|
||||
|
||||
// remove an entry given a pointer to its pointer
|
||||
void remove_common(entry_t **entryptr)
|
||||
{
|
||||
entry_t *entry = *entryptr;
|
||||
*entryptr = entry->next();
|
||||
global_free(entry);
|
||||
}
|
||||
|
||||
// internal state
|
||||
entry_t * m_table[_HashSize];
|
||||
};
|
||||
|
||||
|
||||
// ======================> tagged_list
|
||||
|
||||
class add_exception
|
||||
@ -225,12 +58,12 @@ public:
|
||||
int count() const { return m_list.count(); }
|
||||
|
||||
// remove (free) all objects in the list, leaving an empty list
|
||||
void reset() { m_list.reset(); m_map.reset(); }
|
||||
void reset() { m_list.reset(); m_map.clear(); }
|
||||
|
||||
// add the given object to the head of the list
|
||||
_ElementType &prepend(const char *tag, _ElementType &object)
|
||||
{
|
||||
if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
|
||||
if (!m_map.insert(std::make_pair(tag, &object)).second)
|
||||
throw add_exception(tag);
|
||||
return m_list.prepend(object);
|
||||
}
|
||||
@ -238,100 +71,20 @@ public:
|
||||
// add the given object to the tail of the list
|
||||
_ElementType &append(const char *tag, _ElementType &object)
|
||||
{
|
||||
if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
|
||||
if (!m_map.insert(std::make_pair(tag, &object)).second)
|
||||
throw add_exception(tag);
|
||||
return m_list.append(object);
|
||||
}
|
||||
|
||||
// insert the given object after a particular object (NULL means prepend)
|
||||
_ElementType &insert_after(const char *tag, _ElementType &object, _ElementType *insert_after)
|
||||
{
|
||||
if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
|
||||
throw add_exception(tag);
|
||||
return m_list.insert_after(object, insert_after);
|
||||
}
|
||||
|
||||
// replace an item in the list at the same location, and remove it
|
||||
_ElementType &replace_and_remove(const char *tag, _ElementType &object, _ElementType &toreplace)
|
||||
{
|
||||
m_map.remove(&toreplace);
|
||||
m_list.replace_and_remove(object, toreplace);
|
||||
if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
|
||||
throw add_exception(tag);
|
||||
return object;
|
||||
}
|
||||
|
||||
// detach the given item from the list, but don't free its memory
|
||||
_ElementType &detach(_ElementType &object)
|
||||
{
|
||||
m_map.remove(&object);
|
||||
return m_list.detach(object);
|
||||
}
|
||||
|
||||
// remove the given object and free its memory
|
||||
void remove(_ElementType &object)
|
||||
{
|
||||
m_map.remove(&object);
|
||||
return m_list.remove(object);
|
||||
}
|
||||
|
||||
// find an object by index in the list
|
||||
_ElementType *find(int index) const
|
||||
{
|
||||
return m_list.find(index);
|
||||
}
|
||||
|
||||
// return the index of the given object in the list
|
||||
int indexof(const _ElementType &object) const
|
||||
{
|
||||
return m_list.indexof(object);
|
||||
}
|
||||
|
||||
// operations by tag
|
||||
_ElementType &replace_and_remove(const char *tag, _ElementType &object) { _ElementType *existing = find(tag); return (existing == NULL) ? append(tag, object) : replace_and_remove(tag, object, *existing); }
|
||||
void remove(const char *tag) { _ElementType *object = find(tag); if (object != nullptr) remove(*object); }
|
||||
_ElementType *find(const char *tag) const { return m_map.find_hash_only(tag); }
|
||||
int indexof(const char *tag) const { _ElementType *object = find(tag); return (object != NULL) ? m_list.indexof(*object) : NULL; }
|
||||
void remove(const char *tag) { auto search = m_map.find(tag); if (search != m_map.end()) m_list.remove(*search->second); }
|
||||
_ElementType *find(const char *tag) const { auto search = m_map.find(tag); return (search == m_map.end()) ? nullptr : search->second; }
|
||||
|
||||
private:
|
||||
// internal state
|
||||
simple_list<_ElementType> m_list;
|
||||
tagmap_t<_ElementType *> m_map;
|
||||
std::unordered_map<std::string,_ElementType *> m_map;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// IMPLEMENTATION
|
||||
//**************************************************************************
|
||||
|
||||
//-------------------------------------------------
|
||||
// add_common - core implementation of a tagmap
|
||||
// addition
|
||||
//-------------------------------------------------
|
||||
|
||||
template<class _ElementType, int _HashSize>
|
||||
tagmap_error tagmap_t<_ElementType, _HashSize>::add_common(const char *tag, _ElementType object, bool replace_if_duplicate, bool unique_hash)
|
||||
{
|
||||
UINT32 fullhash = hash(tag);
|
||||
UINT32 hashindex = fullhash % ARRAY_LENGTH(m_table);
|
||||
|
||||
// first make sure we don't have a duplicate
|
||||
for (entry_t *entry = m_table[hashindex]; entry != nullptr; entry = entry->next())
|
||||
if (entry->fullhash() == fullhash)
|
||||
if (unique_hash || entry->tag() == tag)
|
||||
{
|
||||
if (replace_if_duplicate)
|
||||
entry->set_object(object);
|
||||
return TMERR_DUPLICATE;
|
||||
}
|
||||
|
||||
// now allocate a new entry and add to the head of the list
|
||||
auto entry = global_alloc(entry_t(tag, fullhash, object));
|
||||
entry->m_next = m_table[hashindex];
|
||||
m_table[hashindex] = entry;
|
||||
return TMERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
#endif /* __TAGMAP_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user