summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/emualloc.h
blob: 0ed7cc7ea75ec59086ffa4b96f0960b51eb450aa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    emualloc.h

    Memory allocation helpers for the core emulator.

***************************************************************************/

#ifndef MAME_EMU_EMUALLOC_H
#define MAME_EMU_EMUALLOC_H

#pragma once

#include "osdcore.h"
#include "coretmpl.h"

#include <memory>
#include <mutex>
#include <new>


//**************************************************************************
//  MACROS
//**************************************************************************

// pool allocation helpers
#define pool_alloc(_pool, _type)                    (_pool).add_object(global_alloc(_type))
#define pool_alloc_clear(_pool, _type)              (_pool).add_object(global_alloc_clear _type)
#define pool_alloc_array(_pool, _type, _num)        (_pool).add_array(global_alloc_array(_type,_num), (_num))
#define pool_alloc_array_clear(_pool, _type, _num)  (_pool).add_array(global_alloc_array_clear<_type>(_num), (_num))
#define pool_free(_pool, v)                         (_pool).remove(v)



//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************

// resource_pool_item is a base class for items that are tracked by a resource pool
class resource_pool_item
{
private:
	resource_pool_item(const resource_pool_item &) = delete;
	resource_pool_item &operator=(const resource_pool_item &) = delete;

public:
	resource_pool_item(void *ptr, size_t size)
		: m_next(nullptr)
		, m_ordered_next(nullptr)
		, m_ordered_prev(nullptr)
		, m_ptr(ptr)
		, m_size(size)
		, m_id(~osd::u64(0))
	{ }
	virtual ~resource_pool_item() { }

	resource_pool_item *    m_next;
	resource_pool_item *    m_ordered_next;
	resource_pool_item *    m_ordered_prev;
	void *                  m_ptr;
	size_t                  m_size;
	osd::u64                m_id;
};


// a resource_pool_object is a simple object wrapper for the templatized type
template <class ObjectClass>
class resource_pool_object : public resource_pool_item
{
private:
	resource_pool_object(const resource_pool_object<ObjectClass> &) = delete;
	resource_pool_object &operator=(const resource_pool_object<ObjectClass> &) = delete;

public:
	resource_pool_object(ObjectClass *object)
		: resource_pool_item(reinterpret_cast<void *>(object), sizeof(ObjectClass))
		, m_object(object)
	{ }
	resource_pool_object(std::unique_ptr<ObjectClass> &&object)
		: resource_pool_object(object.release())
	{ }
	virtual ~resource_pool_object() { delete m_object; }

private:
	ObjectClass *const      m_object;
};


// a resource_pool_array is a simple object wrapper for an allocated array of
// the templatized type
template <class ObjectClass> class resource_pool_array : public resource_pool_item
{
private:
	resource_pool_array(const resource_pool_array<ObjectClass> &) = delete;
	resource_pool_array &operator=(const resource_pool_array<ObjectClass> &) = delete;

public:
	resource_pool_array(ObjectClass *array, int count)
		: resource_pool_item(reinterpret_cast<void *>(array), sizeof(ObjectClass) * count)
		, m_array(array)
		, m_count(count)
	{ }
	virtual ~resource_pool_array() { delete[] m_array; }

private:
	ObjectClass *const      m_array;
	int const               m_count;
};


// a resource pool tracks items and frees them upon reset or destruction
class resource_pool
{
private:
	resource_pool(const resource_pool &) = delete;
	resource_pool &operator=(const resource_pool &) = delete;

public:
	resource_pool(int hash_size = 193);
	virtual ~resource_pool();

	void add(resource_pool_item &item, size_t size, const char *type);
	void remove(resource_pool_item &item) { remove(item.m_ptr); }
	void remove(void *ptr);
	void remove(const void *ptr) { remove(const_cast<void *>(ptr)); }
	resource_pool_item *find(void *ptr);
	bool contains(void *ptrstart, void *ptrend);
	void clear();

	template <class ObjectClass> ObjectClass *add_object(ObjectClass *object) { add(*new resource_pool_object<ObjectClass>(object), sizeof(ObjectClass), typeid(ObjectClass).name()); return object; }
	template <class ObjectClass> ObjectClass *add_object(std::unique_ptr<ObjectClass> &&object) { return add_object(object.release()); }
	template <class ObjectClass> ObjectClass *add_array(ObjectClass *array, int count) { add(*new resource_pool_array<ObjectClass>(array, count), sizeof(ObjectClass), typeid(ObjectClass).name()); return array; }

private:
	int                     m_hash_size;
	std::mutex              m_listlock;
	std::vector<resource_pool_item *> m_hash;
	resource_pool_item *    m_ordered_head;
	resource_pool_item *    m_ordered_tail;
	static osd::u64         s_id;
};


#endif // MAME_EMU_EMUALLOC_H