Move generic templates from emucore.h to emutempl.h.
Normalize the tagged_list template to wrap a regular standard_list and have similar semantics. Updated a few direct callers to handle the changes.
This commit is contained in:
parent
7a3d9310ee
commit
07a66f8c54
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -653,6 +653,7 @@ src/emu/emuopts.c svneol=native#text/plain
|
||||
src/emu/emuopts.h svneol=native#text/plain
|
||||
src/emu/emupal.c svneol=native#text/plain
|
||||
src/emu/emupal.h svneol=native#text/plain
|
||||
src/emu/emutempl.h svneol=native#text/plain
|
||||
src/emu/fileio.c svneol=native#text/plain
|
||||
src/emu/fileio.h svneol=native#text/plain
|
||||
src/emu/hash.c svneol=native#text/plain
|
||||
|
@ -59,6 +59,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "emucore.h"
|
||||
#include "emutempl.h"
|
||||
#include "express.h"
|
||||
#include <ctype.h>
|
||||
|
||||
@ -444,7 +445,7 @@ void symbol_table::configure_memory(void *param, valid_func valid, read_func rea
|
||||
void symbol_table::add(const char *name, read_write rw, UINT64 *ptr)
|
||||
{
|
||||
m_symlist.remove(name);
|
||||
m_symlist.append(name, global_alloc(integer_symbol_entry(*this, name, rw, ptr)));
|
||||
m_symlist.append(name, *global_alloc(integer_symbol_entry(*this, name, rw, ptr)));
|
||||
}
|
||||
|
||||
|
||||
@ -455,7 +456,7 @@ void symbol_table::add(const char *name, read_write rw, UINT64 *ptr)
|
||||
void symbol_table::add(const char *name, UINT64 value)
|
||||
{
|
||||
m_symlist.remove(name);
|
||||
m_symlist.append(name, global_alloc(integer_symbol_entry(*this, name, value)));
|
||||
m_symlist.append(name, *global_alloc(integer_symbol_entry(*this, name, value)));
|
||||
}
|
||||
|
||||
|
||||
@ -466,7 +467,7 @@ void symbol_table::add(const char *name, UINT64 value)
|
||||
void symbol_table::add(const char *name, void *ref, getter_func getter, setter_func setter)
|
||||
{
|
||||
m_symlist.remove(name);
|
||||
m_symlist.append(name, global_alloc(integer_symbol_entry(*this, name, ref, getter, setter)));
|
||||
m_symlist.append(name, *global_alloc(integer_symbol_entry(*this, name, ref, getter, setter)));
|
||||
}
|
||||
|
||||
|
||||
@ -477,7 +478,7 @@ void symbol_table::add(const char *name, void *ref, getter_func getter, setter_f
|
||||
void symbol_table::add(const char *name, void *ref, int minparams, int maxparams, execute_func execute)
|
||||
{
|
||||
m_symlist.remove(name);
|
||||
m_symlist.append(name, global_alloc(function_symbol_entry(*this, name, ref, minparams, maxparams, execute)));
|
||||
m_symlist.append(name, *global_alloc(function_symbol_entry(*this, name, ref, minparams, maxparams, execute)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -132,7 +132,7 @@ private:
|
||||
// symbol_entry describes a symbol in a symbol table
|
||||
class symbol_entry
|
||||
{
|
||||
friend class tagged_list<symbol_entry>;
|
||||
friend class simple_list<symbol_entry>;
|
||||
|
||||
protected:
|
||||
// symbol types
|
||||
|
@ -115,7 +115,7 @@ void device_list::import_config_list(const device_config_list &list, running_mac
|
||||
for (const device_config *devconfig = list.first(); devconfig != NULL; devconfig = devconfig->next())
|
||||
{
|
||||
device_t *newdevice = devconfig->alloc_device(*m_machine);
|
||||
append(devconfig->tag(), newdevice);
|
||||
append(devconfig->tag(), *newdevice);
|
||||
newdevice->find_interfaces();
|
||||
}
|
||||
}
|
||||
@ -156,8 +156,8 @@ void device_list::start_all()
|
||||
mame_printf_verbose(" (missing dependencies; rescheduling)\n");
|
||||
if (nextdevice == NULL)
|
||||
throw emu_fatalerror("Circular dependency in device startup; unable to start %s '%s'\n", device->name(), device->tag());
|
||||
detach(device);
|
||||
append(device->tag(), device);
|
||||
detach(*device);
|
||||
append(device->tag(), *device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ public:
|
||||
// pull the generic forms forward
|
||||
using super::first;
|
||||
using super::count;
|
||||
using super::index;
|
||||
using super::indexof;
|
||||
using super::find;
|
||||
|
||||
// provide type-specific overrides
|
||||
@ -180,18 +180,18 @@ public:
|
||||
return num;
|
||||
}
|
||||
|
||||
int index(device_type type, T *object) const
|
||||
int indexof(device_type type, T &object) const
|
||||
{
|
||||
int num = 0;
|
||||
for (T *cur = first(type); cur != NULL; cur = cur->typenext(), num++)
|
||||
if (cur == object) return num;
|
||||
if (cur == &object) return num;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int index(device_type type, const char *tag) const
|
||||
int indexof(device_type type, const char *tag) const
|
||||
{
|
||||
T *object = find(tag);
|
||||
return (object != NULL && object->type() == type) ? index(type, object) : -1;
|
||||
return (object != NULL && object->type() == type) ? indexof(type, *object) : -1;
|
||||
}
|
||||
|
||||
T *find(device_type type, int index) const
|
||||
@ -253,7 +253,7 @@ class device_config
|
||||
friend class machine_config;
|
||||
friend class device_t;
|
||||
friend class device_config_interface;
|
||||
template<class T> friend class tagged_list;
|
||||
friend class simple_list<device_config>;
|
||||
|
||||
protected:
|
||||
// construction/destruction
|
||||
@ -376,7 +376,7 @@ class device_t : public bindable_object
|
||||
DISABLE_COPYING(device_t);
|
||||
|
||||
friend class device_interface;
|
||||
template<class T> friend class tagged_list;
|
||||
friend class simple_list<device_t>;
|
||||
friend class device_list;
|
||||
|
||||
protected:
|
||||
|
@ -547,7 +547,7 @@ void device_execute_interface::execute_set_input(int linenum, int state)
|
||||
void device_execute_interface::interface_pre_start()
|
||||
{
|
||||
// fill in the initial states
|
||||
int index = device().machine->m_devicelist.index(&m_device);
|
||||
int index = device().machine->m_devicelist.indexof(m_device);
|
||||
m_suspend = SUSPEND_REASON_RESET;
|
||||
m_profiler = profile_type(index + PROFILER_DEVICE_FIRST);
|
||||
m_inttrigger = index + TRIGGER_INT;
|
||||
|
@ -51,6 +51,7 @@
|
||||
|
||||
// core emulator headers -- must be first
|
||||
#include "emucore.h"
|
||||
#include "emutempl.h"
|
||||
#include "eminline.h"
|
||||
#include "profiler.h"
|
||||
|
||||
|
@ -198,6 +198,16 @@ inline void operator--(_Type &value) { value = (_Type)((int)value - 1); } \
|
||||
inline void operator--(_Type &value, int) { value = (_Type)((int)value - 1); }
|
||||
|
||||
|
||||
// this macro wraps a function 'x' and can be used to pass a function followed by its name
|
||||
#define FUNC(x) x, #x
|
||||
|
||||
// this macro wraps a member function 'x' from class 'c'
|
||||
#define MFUNC(c,x) &c::x, #c "::" #x
|
||||
|
||||
// this macro wraps a member function 'x' from class 'c' using a templatized stub of type 's'
|
||||
#define MSTUB(s,c,x) s##_stub<c, &c::x>, #c "::" #x
|
||||
|
||||
|
||||
// standard assertion macros
|
||||
#undef assert
|
||||
#undef assert_always
|
||||
@ -346,326 +356,6 @@ inline _Dest crosscast(_Source *src)
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// COMMON TEMPLATES
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> simple_list
|
||||
|
||||
template<class T>
|
||||
class simple_list
|
||||
{
|
||||
DISABLE_COPYING(simple_list);
|
||||
|
||||
T *m_head;
|
||||
T *m_tail;
|
||||
resource_pool &m_pool;
|
||||
int m_count;
|
||||
|
||||
public:
|
||||
simple_list(resource_pool &pool = global_resource_pool) :
|
||||
m_head(NULL),
|
||||
m_tail(NULL),
|
||||
m_pool(pool),
|
||||
m_count(0) { }
|
||||
|
||||
virtual ~simple_list() { reset(); }
|
||||
|
||||
resource_pool &pool() const { return m_pool; }
|
||||
|
||||
T *first() const { return m_head; }
|
||||
T *last() const { return m_tail; }
|
||||
int count() const { return m_count; }
|
||||
|
||||
void reset() { while (m_head != NULL) remove(*m_head); }
|
||||
|
||||
T &prepend(T &object)
|
||||
{
|
||||
object.m_next = m_head;
|
||||
m_head = &object;
|
||||
if (m_tail == NULL)
|
||||
m_tail = m_head;
|
||||
m_count++;
|
||||
return object;
|
||||
}
|
||||
|
||||
void prepend_list(simple_list<T> &list)
|
||||
{
|
||||
int count = list.count();
|
||||
if (count == 0)
|
||||
return;
|
||||
T *tail = list.last();
|
||||
T *head = list.detach_all();
|
||||
tail->m_next = m_head;
|
||||
m_head = head;
|
||||
if (m_tail == NULL)
|
||||
m_tail = tail;
|
||||
m_count += count;
|
||||
}
|
||||
|
||||
T &append(T &object)
|
||||
{
|
||||
object.m_next = NULL;
|
||||
if (m_tail != NULL)
|
||||
m_tail = m_tail->m_next = &object;
|
||||
else
|
||||
m_tail = m_head = &object;
|
||||
m_count++;
|
||||
return object;
|
||||
}
|
||||
|
||||
void append_list(simple_list<T> &list)
|
||||
{
|
||||
int count = list.count();
|
||||
if (count == 0)
|
||||
return;
|
||||
T *tail = list.last();
|
||||
T *head = list.detach_all();
|
||||
if (m_tail != NULL)
|
||||
m_tail->m_next = head;
|
||||
else
|
||||
m_head = head;
|
||||
m_tail = tail;
|
||||
m_count += count;
|
||||
}
|
||||
|
||||
T &insert_after(T &object, T *insert_after)
|
||||
{
|
||||
if (insert_after == NULL)
|
||||
return prepend(object);
|
||||
object.m_next = insert_after->m_next;
|
||||
insert_after->m_next = &object;
|
||||
m_count++;
|
||||
return object;
|
||||
}
|
||||
|
||||
T *detach_head()
|
||||
{
|
||||
T *result = m_head;
|
||||
if (result != NULL)
|
||||
{
|
||||
m_head = result->m_next;
|
||||
m_count--;
|
||||
if (m_head == NULL)
|
||||
m_tail = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
T &detach(T &object)
|
||||
{
|
||||
T *prev = NULL;
|
||||
for (T *cur = m_head; cur != NULL; prev = cur, cur = cur->m_next)
|
||||
if (cur == &object)
|
||||
{
|
||||
if (prev != NULL)
|
||||
prev->m_next = object.m_next;
|
||||
else
|
||||
m_head = object.m_next;
|
||||
if (m_tail == &object)
|
||||
m_tail = prev;
|
||||
m_count--;
|
||||
return object;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
T *detach_all()
|
||||
{
|
||||
T *result = m_head;
|
||||
m_head = m_tail = NULL;
|
||||
m_count = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
void remove(T &object)
|
||||
{
|
||||
detach(object);
|
||||
pool_free(m_pool, &object);
|
||||
}
|
||||
|
||||
T *find(int index) const
|
||||
{
|
||||
for (T *cur = m_head; cur != NULL; cur = cur->m_next)
|
||||
if (index-- == 0)
|
||||
return cur;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int indexof(const T &object) const
|
||||
{
|
||||
int index = 0;
|
||||
for (T *cur = m_head; cur != NULL; cur = cur->m_next)
|
||||
{
|
||||
if (cur == &object)
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// ======================> fixed_allocator
|
||||
|
||||
template<class T>
|
||||
class fixed_allocator
|
||||
{
|
||||
DISABLE_COPYING(fixed_allocator);
|
||||
|
||||
public:
|
||||
fixed_allocator(resource_pool &pool = global_resource_pool)
|
||||
: m_pool(pool),
|
||||
m_freelist(pool) { }
|
||||
|
||||
T *alloc()
|
||||
{
|
||||
T *result = m_freelist.detach_head();
|
||||
if (result == NULL)
|
||||
result = m_pool.add_object(new T);
|
||||
return result;
|
||||
}
|
||||
|
||||
void reclaim(T *item) { if (item != NULL) m_freelist.append(*item); }
|
||||
void reclaim(T &item) { m_freelist.append(item); }
|
||||
void reclaim_all(simple_list<T> &list) { m_freelist.append_list(list); }
|
||||
|
||||
private:
|
||||
resource_pool &m_pool;
|
||||
simple_list<T> m_freelist;
|
||||
};
|
||||
|
||||
|
||||
// ======================> tagged_list
|
||||
|
||||
template<class T>
|
||||
class tagged_list
|
||||
{
|
||||
DISABLE_COPYING(tagged_list);
|
||||
|
||||
T *m_head;
|
||||
T **m_tailptr;
|
||||
tagmap_t<T *> m_map;
|
||||
resource_pool &m_pool;
|
||||
|
||||
public:
|
||||
tagged_list(resource_pool &pool = global_resource_pool) :
|
||||
m_head(NULL),
|
||||
m_tailptr(&m_head),
|
||||
m_pool(pool) { }
|
||||
|
||||
virtual ~tagged_list()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
while (m_head != NULL)
|
||||
remove(m_head);
|
||||
}
|
||||
|
||||
T *first() const { return m_head; }
|
||||
|
||||
int count() const
|
||||
{
|
||||
int num = 0;
|
||||
for (T *cur = m_head; cur != NULL; cur = cur->m_next)
|
||||
num++;
|
||||
return num;
|
||||
}
|
||||
|
||||
int index(T *object) const
|
||||
{
|
||||
int num = 0;
|
||||
for (T *cur = m_head; cur != NULL; cur = cur->m_next)
|
||||
if (cur == object)
|
||||
return num;
|
||||
else
|
||||
num++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int index(const char *tag) const
|
||||
{
|
||||
T *object = find(tag);
|
||||
return (object != NULL) ? index(object) : -1;
|
||||
}
|
||||
|
||||
T *replace(const char *tag, T *object)
|
||||
{
|
||||
T *existing = find(tag);
|
||||
if (existing == NULL)
|
||||
return append(tag, object);
|
||||
|
||||
for (T **objectptr = &m_head; *objectptr != NULL; objectptr = &(*objectptr)->m_next)
|
||||
if (*objectptr == existing)
|
||||
{
|
||||
*objectptr = object;
|
||||
object->m_next = existing->m_next;
|
||||
if (m_tailptr == &existing->m_next)
|
||||
m_tailptr = &object->m_next;
|
||||
m_map.remove(existing);
|
||||
pool_free(m_pool, existing);
|
||||
if (m_map.add_unique_hash(tag, object, false) != TMERR_NONE)
|
||||
throw emu_fatalerror("Error replacing object named '%s'", tag);
|
||||
break;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
T *append(const char *tag, T *object, bool replace_if_duplicate = false)
|
||||
{
|
||||
if (m_map.add_unique_hash(tag, object, false) != TMERR_NONE)
|
||||
throw emu_fatalerror("Error adding object named '%s'", tag);
|
||||
*m_tailptr = object;
|
||||
object->m_next = NULL;
|
||||
m_tailptr = &object->m_next;
|
||||
return object;
|
||||
}
|
||||
|
||||
void detach(T *object)
|
||||
{
|
||||
for (T **objectptr = &m_head; *objectptr != NULL; objectptr = &(*objectptr)->m_next)
|
||||
if (*objectptr == object)
|
||||
{
|
||||
*objectptr = object->m_next;
|
||||
if (m_tailptr == &object->m_next)
|
||||
m_tailptr = objectptr;
|
||||
m_map.remove(object);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void remove(T *object)
|
||||
{
|
||||
detach(object);
|
||||
pool_free(m_pool, object);
|
||||
}
|
||||
|
||||
void remove(const char *tag)
|
||||
{
|
||||
T *object = find(tag);
|
||||
if (object != NULL)
|
||||
remove(object);
|
||||
}
|
||||
|
||||
T *find(const char *tag) const
|
||||
{
|
||||
return m_map.find_hash_only(tag);
|
||||
}
|
||||
|
||||
T *find(int index) const
|
||||
{
|
||||
for (T *cur = m_head; cur != NULL; cur = cur->m_next)
|
||||
if (index-- == 0)
|
||||
return cur;
|
||||
return NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// FUNCTION PROTOTYPES
|
||||
//**************************************************************************
|
||||
|
380
src/emu/emutempl.h
Normal file
380
src/emu/emutempl.h
Normal file
@ -0,0 +1,380 @@
|
||||
/***************************************************************************
|
||||
|
||||
emutempl.h
|
||||
|
||||
Core templates for basic non-string types.
|
||||
|
||||
****************************************************************************
|
||||
|
||||
Copyright Aaron Giles
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name 'MAME' nor the names of its contributors may be
|
||||
used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __EMUTEMPL_H__
|
||||
#define __EMUTEMPL_H__
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TYPE DEFINITIONS
|
||||
//**************************************************************************
|
||||
|
||||
// ======================> simple_list
|
||||
|
||||
// a simple_list is a singly-linked list whose 'next' pointer is owned
|
||||
// by the object
|
||||
template<class T>
|
||||
class simple_list
|
||||
{
|
||||
// we don't support deep copying
|
||||
DISABLE_COPYING(simple_list);
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
simple_list(resource_pool &pool = global_resource_pool) :
|
||||
m_head(NULL),
|
||||
m_tail(NULL),
|
||||
m_pool(pool),
|
||||
m_count(0) { }
|
||||
|
||||
virtual ~simple_list() { reset(); }
|
||||
|
||||
// simple getters
|
||||
resource_pool &pool() const { return m_pool; }
|
||||
T *first() const { return m_head; }
|
||||
T *last() const { return m_tail; }
|
||||
int count() const { return m_count; }
|
||||
|
||||
// remove (free) all objects in the list, leaving an empty list
|
||||
void reset()
|
||||
{
|
||||
while (m_head != NULL)
|
||||
remove(*m_head);
|
||||
}
|
||||
|
||||
// add the given object to the head of the list
|
||||
T &prepend(T &object)
|
||||
{
|
||||
object.m_next = m_head;
|
||||
m_head = &object;
|
||||
if (m_tail == NULL)
|
||||
m_tail = m_head;
|
||||
m_count++;
|
||||
return object;
|
||||
}
|
||||
|
||||
// add the given list to the head of the list
|
||||
void prepend_list(simple_list<T> &list)
|
||||
{
|
||||
int count = list.count();
|
||||
if (count == 0)
|
||||
return;
|
||||
T *tail = list.last();
|
||||
T *head = list.detach_all();
|
||||
tail->m_next = m_head;
|
||||
m_head = head;
|
||||
if (m_tail == NULL)
|
||||
m_tail = tail;
|
||||
m_count += count;
|
||||
}
|
||||
|
||||
// add the given object to the tail of the list
|
||||
T &append(T &object)
|
||||
{
|
||||
object.m_next = NULL;
|
||||
if (m_tail != NULL)
|
||||
m_tail = m_tail->m_next = &object;
|
||||
else
|
||||
m_tail = m_head = &object;
|
||||
m_count++;
|
||||
return object;
|
||||
}
|
||||
|
||||
// add the given list to the tail of the list
|
||||
void append_list(simple_list<T> &list)
|
||||
{
|
||||
int count = list.count();
|
||||
if (count == 0)
|
||||
return;
|
||||
T *tail = list.last();
|
||||
T *head = list.detach_all();
|
||||
if (m_tail != NULL)
|
||||
m_tail->m_next = head;
|
||||
else
|
||||
m_head = head;
|
||||
m_tail = tail;
|
||||
m_count += count;
|
||||
}
|
||||
|
||||
// insert the given object after a particular object (NULL means prepend)
|
||||
T &insert_after(T &object, T *insert_after)
|
||||
{
|
||||
if (insert_after == NULL)
|
||||
return prepend(object);
|
||||
object.m_next = insert_after->m_next;
|
||||
insert_after->m_next = &object;
|
||||
m_count++;
|
||||
return object;
|
||||
}
|
||||
|
||||
// replace an item in the list at the same location, and remove it
|
||||
T &replace_and_remove(T &object, T &toreplace)
|
||||
{
|
||||
T *prev = NULL;
|
||||
for (T *cur = m_head; cur != NULL; prev = cur, cur = cur->m_next)
|
||||
if (cur == &toreplace)
|
||||
{
|
||||
if (prev != NULL)
|
||||
prev->m_next = &object;
|
||||
else
|
||||
m_head = &object;
|
||||
if (m_tail == &toreplace)
|
||||
m_tail = &object;
|
||||
object.m_next = toreplace.m_next;
|
||||
pool_free(m_pool, &toreplace);
|
||||
return object;
|
||||
}
|
||||
return append(object);
|
||||
}
|
||||
|
||||
// detach the head item from the list, but don't free its memory
|
||||
T *detach_head()
|
||||
{
|
||||
T *result = m_head;
|
||||
if (result != NULL)
|
||||
{
|
||||
m_head = result->m_next;
|
||||
m_count--;
|
||||
if (m_head == NULL)
|
||||
m_tail = NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// detach the given item from the list, but don't free its memory
|
||||
T &detach(T &object)
|
||||
{
|
||||
T *prev = NULL;
|
||||
for (T *cur = m_head; cur != NULL; prev = cur, cur = cur->m_next)
|
||||
if (cur == &object)
|
||||
{
|
||||
if (prev != NULL)
|
||||
prev->m_next = object.m_next;
|
||||
else
|
||||
m_head = object.m_next;
|
||||
if (m_tail == &object)
|
||||
m_tail = prev;
|
||||
m_count--;
|
||||
return object;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
// deatch the entire list, returning the head, but don't free memory
|
||||
T *detach_all()
|
||||
{
|
||||
T *result = m_head;
|
||||
m_head = m_tail = NULL;
|
||||
m_count = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
// remove the given object and free its memory
|
||||
void remove(T &object)
|
||||
{
|
||||
detach(object);
|
||||
pool_free(m_pool, &object);
|
||||
}
|
||||
|
||||
// find an object by index in the list
|
||||
T *find(int index) const
|
||||
{
|
||||
for (T *cur = m_head; cur != NULL; cur = cur->m_next)
|
||||
if (index-- == 0)
|
||||
return cur;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// return the index of the given object in the list
|
||||
int indexof(const T &object) const
|
||||
{
|
||||
int index = 0;
|
||||
for (T *cur = m_head; cur != NULL; cur = cur->m_next)
|
||||
{
|
||||
if (cur == &object)
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private:
|
||||
// internal state
|
||||
T * m_head; // head of the singly-linked list
|
||||
T * m_tail; // tail of the singly-linked list
|
||||
resource_pool & m_pool; // resource pool where objects are freed
|
||||
int m_count; // number of objects in the list
|
||||
};
|
||||
|
||||
|
||||
// ======================> fixed_allocator
|
||||
|
||||
// a fixed_allocator is a simple class that maintains a free pool of objects
|
||||
template<class T>
|
||||
class fixed_allocator
|
||||
{
|
||||
// we don't support deep copying
|
||||
DISABLE_COPYING(fixed_allocator);
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
fixed_allocator(resource_pool &pool = global_resource_pool)
|
||||
: m_freelist(pool) { }
|
||||
|
||||
// allocate a new item, either by recycling an old one, or by allocating a new one
|
||||
T *alloc()
|
||||
{
|
||||
T *result = m_freelist.detach_head();
|
||||
if (result == NULL)
|
||||
result = m_freelist.pool().add_object(new T);
|
||||
return result;
|
||||
}
|
||||
|
||||
// reclaim an item by adding it to the free list
|
||||
void reclaim(T *item) { if (item != NULL) m_freelist.append(*item); }
|
||||
void reclaim(T &item) { m_freelist.append(item); }
|
||||
|
||||
// reclaim all items from a list
|
||||
void reclaim_all(simple_list<T> &list) { m_freelist.append_list(list); }
|
||||
|
||||
private:
|
||||
// internal state
|
||||
simple_list<T> m_freelist; // list of free objects
|
||||
};
|
||||
|
||||
|
||||
// ======================> tagged_list
|
||||
|
||||
// a tagged_list is a class that maintains a list of objects that can be quickly looked up by tag
|
||||
template<class T>
|
||||
class tagged_list
|
||||
{
|
||||
// we don't support deep copying
|
||||
DISABLE_COPYING(tagged_list);
|
||||
|
||||
public:
|
||||
// construction/destruction
|
||||
tagged_list(resource_pool &pool = global_resource_pool) :
|
||||
m_list(pool) { }
|
||||
|
||||
// simple getters
|
||||
resource_pool &pool() const { return m_list.pool(); }
|
||||
T *first() const { return m_list.first(); }
|
||||
T *last() const { return m_list.last(); }
|
||||
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(); }
|
||||
|
||||
// add the given object to the head of the list
|
||||
T &prepend(const char *tag, T &object)
|
||||
{
|
||||
if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
|
||||
throw emu_fatalerror("Error adding object named '%s'", tag);
|
||||
return m_list.prepend(object);
|
||||
}
|
||||
|
||||
// add the given object to the tail of the list
|
||||
T &append(const char *tag, T &object)
|
||||
{
|
||||
if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
|
||||
throw emu_fatalerror("Error adding object named '%s'", tag);
|
||||
return m_list.append(object);
|
||||
}
|
||||
|
||||
// insert the given object after a particular object (NULL means prepend)
|
||||
T &insert_after(const char *tag, T &object, T *insert_after)
|
||||
{
|
||||
if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
|
||||
throw emu_fatalerror("Error adding object named '%s'", tag);
|
||||
return m_list.insert_after(object, insert_after);
|
||||
}
|
||||
|
||||
// replace an item in the list at the same location, and remove it
|
||||
T &replace_and_remove(const char *tag, T &object, T &toreplace)
|
||||
{
|
||||
m_map.remove(&toreplace);
|
||||
m_list.replace_and_remove(object, toreplace);
|
||||
if (m_map.add_unique_hash(tag, &object, false) != TMERR_NONE)
|
||||
throw emu_fatalerror("Error replacing object named '%s'", tag);
|
||||
return object;
|
||||
}
|
||||
|
||||
// detach the given item from the list, but don't free its memory
|
||||
T &detach(T &object)
|
||||
{
|
||||
m_map.remove(&object);
|
||||
return m_list.detach(object);
|
||||
}
|
||||
|
||||
// remove the given object and free its memory
|
||||
void remove(T &object)
|
||||
{
|
||||
m_map.remove(&object);
|
||||
return m_list.remove(object);
|
||||
}
|
||||
|
||||
// find an object by index in the list
|
||||
T *find(int index) const
|
||||
{
|
||||
return m_list.find(index);
|
||||
}
|
||||
|
||||
// return the index of the given object in the list
|
||||
int indexof(const T &object) const
|
||||
{
|
||||
return m_list.indexof(object);
|
||||
}
|
||||
|
||||
// operations by tag
|
||||
T &replace_and_remove(const char *tag, T &object) { T *existing = find(tag); return (existing == NULL) ? append(tag, object) : replace_and_remove(tag, object, *existing); }
|
||||
void remove(const char *tag) { T *object = find(tag); if (object != NULL) remove(*object); }
|
||||
T *find(const char *tag) const { return m_map.find_hash_only(tag); }
|
||||
int indexof(const char *tag) const { T *object = find(tag); return (object != NULL) ? m_list.indexof(*object) : NULL; }
|
||||
|
||||
private:
|
||||
// internal state
|
||||
simple_list<T> m_list;
|
||||
tagmap_t<T *> m_map;
|
||||
};
|
||||
|
||||
|
||||
#endif /* __EMUTEMPL_H__ */
|
@ -514,19 +514,19 @@ void image_add_device_with_subdevices(device_t *owner, device_type type, const c
|
||||
machine_config *config = (machine_config *)owner->machine->config;
|
||||
|
||||
device_config *devconfig = type(*config, owner->subtag(tempstring,tag), &owner->baseconfig(), clock);
|
||||
device_t *device = device_list->append(devconfig->tag(), devconfig->alloc_device(*owner->machine));
|
||||
device_t &device = device_list->append(devconfig->tag(), *devconfig->alloc_device(*owner->machine));
|
||||
|
||||
machine_config_constructor machconfig = device->machine_config_additions();
|
||||
machine_config_constructor machconfig = device.machine_config_additions();
|
||||
if (machconfig != NULL)
|
||||
{
|
||||
(*machconfig)(*config, devconfig);
|
||||
for (const device_config *config_dev = config->m_devicelist.first(); config_dev != NULL; config_dev = config_dev->next())
|
||||
{
|
||||
if (config_dev->owner()==devconfig) {
|
||||
device_list->append(config_dev->tag(), config_dev->alloc_device(*owner->machine));
|
||||
device_list->append(config_dev->tag(), *config_dev->alloc_device(*owner->machine));
|
||||
}
|
||||
}
|
||||
}
|
||||
config->m_devicelist.append(devconfig->tag(), devconfig);
|
||||
config->m_devicelist.append(devconfig->tag(), *devconfig);
|
||||
}
|
||||
|
||||
|
@ -2911,7 +2911,7 @@ static void port_config_detokenize(ioport_list &portlist, const input_port_token
|
||||
maskbits = 0;
|
||||
|
||||
string = TOKEN_GET_STRING(ipt);
|
||||
curport = portlist.append(string, global_alloc(input_port_config(string)));
|
||||
curport = &portlist.append(string, *global_alloc(input_port_config(string)));
|
||||
curfield = NULL;
|
||||
cursetting = NULL;
|
||||
break;
|
||||
|
@ -274,7 +274,7 @@ void running_machine::start()
|
||||
m_scheduler.register_for_save();
|
||||
|
||||
// allocate a soft_reset timer
|
||||
m_soft_reset_timer = m_scheduler.timer_alloc(MFUNC(timer_expired, running_machine, soft_reset), this);
|
||||
m_soft_reset_timer = m_scheduler.timer_alloc(MSTUB(timer_expired, running_machine, soft_reset), this);
|
||||
|
||||
// init the osd layer
|
||||
m_osd.init(*this);
|
||||
@ -616,7 +616,7 @@ memory_region *running_machine::region_alloc(const char *name, UINT32 length, UI
|
||||
fatalerror("region_alloc called with duplicate region name \"%s\"\n", name);
|
||||
|
||||
// allocate the region
|
||||
return m_regionlist.append(name, auto_alloc(this, memory_region(*this, name, length, flags)));
|
||||
return &m_regionlist.append(name, *auto_alloc(this, memory_region(*this, name, length, flags)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -221,7 +221,7 @@ class memory_region
|
||||
DISABLE_COPYING(memory_region);
|
||||
|
||||
friend class running_machine;
|
||||
template<class T> friend class tagged_list;
|
||||
friend class simple_list<memory_region>;
|
||||
friend resource_pool_object<memory_region>::~resource_pool_object();
|
||||
|
||||
// construction/destruction
|
||||
|
@ -522,7 +522,7 @@ void riot6532_device::device_start()
|
||||
assert(this != NULL);
|
||||
|
||||
/* set static values */
|
||||
m_index = m_machine.m_devicelist.index(RIOT6532, tag());
|
||||
m_index = m_machine.m_devicelist.indexof(RIOT6532, tag());
|
||||
|
||||
/* configure the ports */
|
||||
devcb_resolve_read8(&m_port[0].m_in_func, &m_config.m_in_a_func, this);
|
||||
|
@ -120,7 +120,7 @@ device_config *machine_config::device_add(device_config *owner, const char *tag,
|
||||
{
|
||||
astring tempstring;
|
||||
const char *fulltag = owner->subtag(tempstring, tag);
|
||||
return m_devicelist.append(fulltag, (*type)(*this, fulltag, owner, clock));
|
||||
return &m_devicelist.append(fulltag, *(*type)(*this, fulltag, owner, clock));
|
||||
}
|
||||
|
||||
|
||||
@ -133,7 +133,7 @@ device_config *machine_config::device_replace(device_config *owner, const char *
|
||||
{
|
||||
astring tempstring;
|
||||
const char *fulltag = owner->subtag(tempstring, tag);
|
||||
return m_devicelist.replace(fulltag, (*type)(*this, fulltag, owner, clock));
|
||||
return &m_devicelist.replace_and_remove(fulltag, *(*type)(*this, fulltag, owner, clock));
|
||||
}
|
||||
|
||||
|
||||
|
@ -198,7 +198,7 @@ static int get_variable_value(running_machine &machine, const char *string, char
|
||||
// screen 0 parameters
|
||||
for (const screen_device_config *devconfig = machine.m_config.first_screen(); devconfig != NULL; devconfig = devconfig->next_screen())
|
||||
{
|
||||
int scrnum = machine.m_config.m_devicelist.index(SCREEN, devconfig->tag());
|
||||
int scrnum = machine.m_config.m_devicelist.indexof(SCREEN, devconfig->tag());
|
||||
|
||||
// native X aspect factor
|
||||
sprintf(temp, "~scr%dnativexaspect~", scrnum);
|
||||
|
@ -532,7 +532,7 @@ void device_scheduler::trigger(int trigid, attotime after)
|
||||
|
||||
// if we have a non-zero time, schedule a timer
|
||||
if (after != attotime::zero)
|
||||
timer_set(after, MFUNC(timer_expired, device_scheduler, timed_trigger), trigid, this);
|
||||
timer_set(after, MSTUB(timer_expired, device_scheduler, timed_trigger), trigid, this);
|
||||
|
||||
// send the trigger to everyone who cares
|
||||
else
|
||||
|
@ -51,13 +51,6 @@
|
||||
// MACROS
|
||||
//**************************************************************************
|
||||
|
||||
// this macro wraps a function 'x' and can be used to pass a function followed by its name
|
||||
#define FUNC(x) x, #x
|
||||
|
||||
// this macro wraps a member function 'x' from class 'c' using a templatized stub of type 's'
|
||||
#define MFUNC(s,c,x) s##_stub<c, &c::x>, #c "::" #x
|
||||
|
||||
|
||||
// macro for the RC time constant on a 74LS123 with C > 1000pF
|
||||
// R is in ohms, C is in farads
|
||||
#define TIME_OF_74LS123(r,c) (0.45 * (double)(r) * (double)(c))
|
||||
|
@ -1063,7 +1063,7 @@ void video_manager::create_snapshot_bitmap(device_t *screen)
|
||||
// select the appropriate view in our dummy target
|
||||
if (m_snap_native && screen != NULL)
|
||||
{
|
||||
int view_index = m_machine.m_devicelist.index(SCREEN, screen->tag());
|
||||
int view_index = m_machine.m_devicelist.indexof(SCREEN, screen->tag());
|
||||
assert(view_index != -1);
|
||||
m_snap_target->set_view(view_index);
|
||||
}
|
||||
|
@ -4576,7 +4576,7 @@ static DEVICE_START( voodoo )
|
||||
}
|
||||
|
||||
/* set the type, and initialize the chip mask */
|
||||
v->index = device->machine->m_devicelist.index(device->type(), device->tag());
|
||||
v->index = device->machine->m_devicelist.indexof(device->type(), device->tag());
|
||||
v->screen = downcast<screen_device *>(device->machine->device(config->screen));
|
||||
assert_always(v->screen != NULL, "Unable to find screen attached to voodoo");
|
||||
v->cpu = device->machine->device(config->cputag);
|
||||
|
@ -97,6 +97,7 @@ void tagmap_reset(tagmap *map)
|
||||
next = entry->next;
|
||||
free(entry);
|
||||
}
|
||||
map->table[hashindex] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1809,7 +1809,7 @@ static DEVICE_START( naomibd )
|
||||
}
|
||||
|
||||
/* set the type */
|
||||
v->index = device->machine->m_devicelist.index(device->type(), device->tag());
|
||||
v->index = device->machine->m_devicelist.indexof(device->type(), device->tag());
|
||||
v->type = config->type;
|
||||
|
||||
/* initialize some registers */
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <windows.h>
|
||||
|
||||
// MAME headers
|
||||
#include "emucore.h"
|
||||
#include "emu.h"
|
||||
|
||||
// MAMEOS headers
|
||||
#include "window.h"
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include <windows.h>
|
||||
|
||||
// MAME headers
|
||||
#include "emucore.h"
|
||||
#include "emu.h"
|
||||
|
||||
// MAMEOS headers
|
||||
#include "window.h"
|
||||
|
@ -43,6 +43,8 @@
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "window.h"
|
||||
|
||||
//============================================================
|
||||
|
Loading…
Reference in New Issue
Block a user