1848b8605Smrg/**
2848b8605Smrg * \file hash.h
3848b8605Smrg * Generic hash table.
4848b8605Smrg */
5848b8605Smrg
6848b8605Smrg/*
7848b8605Smrg * Mesa 3-D graphics library
8848b8605Smrg *
9848b8605Smrg * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
10848b8605Smrg *
11848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
12848b8605Smrg * copy of this software and associated documentation files (the "Software"),
13848b8605Smrg * to deal in the Software without restriction, including without limitation
14848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
16848b8605Smrg * Software is furnished to do so, subject to the following conditions:
17848b8605Smrg *
18848b8605Smrg * The above copyright notice and this permission notice shall be included
19848b8605Smrg * in all copies or substantial portions of the Software.
20848b8605Smrg *
21848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
24848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
25848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
26848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
28848b8605Smrg */
29848b8605Smrg
30848b8605Smrg
31848b8605Smrg#ifndef HASH_H
32848b8605Smrg#define HASH_H
33848b8605Smrg
34848b8605Smrg
35848b8605Smrg#include "glheader.h"
36b8e80941Smrg#include "imports.h"
37b8e80941Smrg#include "c11/threads.h"
38848b8605Smrg
39b8e80941Smrg/**
40b8e80941Smrg * Magic GLuint object name that gets stored outside of the struct hash_table.
41b8e80941Smrg *
42b8e80941Smrg * The hash table needs a particular pointer to be the marker for a key that
43b8e80941Smrg * was deleted from the table, along with NULL for the "never allocated in the
44b8e80941Smrg * table" marker.  Legacy GL allows any GLuint to be used as a GL object name,
45b8e80941Smrg * and we use a 1:1 mapping from GLuints to key pointers, so we need to be
46b8e80941Smrg * able to track a GLuint that happens to match the deleted key outside of
47b8e80941Smrg * struct hash_table.  We tell the hash table to use "1" as the deleted key
48b8e80941Smrg * value, so that we test the deleted-key-in-the-table path as best we can.
49b8e80941Smrg */
50b8e80941Smrg#define DELETED_KEY_VALUE 1
51b8e80941Smrg
52b8e80941Smrg/** @{
53b8e80941Smrg * Mapping from our use of GLuint as both the key and the hash value to the
54b8e80941Smrg * hash_table.h API
55b8e80941Smrg *
56b8e80941Smrg * There exist many integer hash functions, designed to avoid collisions when
57b8e80941Smrg * the integers are spread across key space with some patterns.  In GL, the
58b8e80941Smrg * pattern (in the case of glGen*()ed object IDs) is that the keys are unique
59b8e80941Smrg * contiguous integers starting from 1.  Because of that, we just use the key
60b8e80941Smrg * as the hash value, to minimize the cost of the hash function.  If objects
61b8e80941Smrg * are never deleted, we will never see a collision in the table, because the
62b8e80941Smrg * table resizes itself when it approaches full, and thus key % table_size ==
63b8e80941Smrg * key.
64b8e80941Smrg *
65b8e80941Smrg * The case where we could have collisions for genned objects would be
66b8e80941Smrg * something like: glGenBuffers(&a, 100); glDeleteBuffers(&a + 50, 50);
67b8e80941Smrg * glGenBuffers(&b, 100), because objects 1-50 and 101-200 are allocated at
68b8e80941Smrg * the end of that sequence, instead of 1-150.  So far it doesn't appear to be
69b8e80941Smrg * a problem.
70b8e80941Smrg */
71b8e80941Smrgstatic inline bool
72b8e80941Smrguint_key_compare(const void *a, const void *b)
73b8e80941Smrg{
74b8e80941Smrg   return a == b;
75b8e80941Smrg}
76b8e80941Smrg
77b8e80941Smrgstatic inline uint32_t
78b8e80941Smrguint_hash(GLuint id)
79b8e80941Smrg{
80b8e80941Smrg   return id;
81b8e80941Smrg}
82b8e80941Smrg
83b8e80941Smrgstatic inline uint32_t
84b8e80941Smrguint_key_hash(const void *key)
85b8e80941Smrg{
86b8e80941Smrg   return uint_hash((uintptr_t)key);
87b8e80941Smrg}
88b8e80941Smrg
89b8e80941Smrgstatic inline void *
90b8e80941Smrguint_key(GLuint id)
91b8e80941Smrg{
92b8e80941Smrg   return (void *)(uintptr_t) id;
93b8e80941Smrg}
94b8e80941Smrg/** @} */
95b8e80941Smrg
96b8e80941Smrg/**
97b8e80941Smrg * The hash table data structure.
98b8e80941Smrg */
99b8e80941Smrgstruct _mesa_HashTable {
100b8e80941Smrg   struct hash_table *ht;
101b8e80941Smrg   GLuint MaxKey;                        /**< highest key inserted so far */
102b8e80941Smrg   mtx_t Mutex;                          /**< mutual exclusion lock */
103b8e80941Smrg   GLboolean InDeleteAll;                /**< Debug check */
104b8e80941Smrg   /** Value that would be in the table for DELETED_KEY_VALUE. */
105b8e80941Smrg   void *deleted_key_data;
106b8e80941Smrg};
107848b8605Smrg
108848b8605Smrgextern struct _mesa_HashTable *_mesa_NewHashTable(void);
109848b8605Smrg
110848b8605Smrgextern void _mesa_DeleteHashTable(struct _mesa_HashTable *table);
111848b8605Smrg
112848b8605Smrgextern void *_mesa_HashLookup(struct _mesa_HashTable *table, GLuint key);
113848b8605Smrg
114848b8605Smrgextern void _mesa_HashInsert(struct _mesa_HashTable *table, GLuint key, void *data);
115848b8605Smrg
116848b8605Smrgextern void _mesa_HashRemove(struct _mesa_HashTable *table, GLuint key);
117848b8605Smrg
118b8e80941Smrg/**
119b8e80941Smrg * Lock the hash table mutex.
120b8e80941Smrg *
121b8e80941Smrg * This function should be used when multiple objects need
122b8e80941Smrg * to be looked up in the hash table, to avoid having to lock
123b8e80941Smrg * and unlock the mutex each time.
124b8e80941Smrg *
125b8e80941Smrg * \param table the hash table.
126b8e80941Smrg */
127b8e80941Smrgstatic inline void
128b8e80941Smrg_mesa_HashLockMutex(struct _mesa_HashTable *table)
129b8e80941Smrg{
130b8e80941Smrg   assert(table);
131b8e80941Smrg   mtx_lock(&table->Mutex);
132b8e80941Smrg}
133b8e80941Smrg
134848b8605Smrg
135b8e80941Smrg/**
136b8e80941Smrg * Unlock the hash table mutex.
137b8e80941Smrg *
138b8e80941Smrg * \param table the hash table.
139b8e80941Smrg */
140b8e80941Smrgstatic inline void
141b8e80941Smrg_mesa_HashUnlockMutex(struct _mesa_HashTable *table)
142b8e80941Smrg{
143b8e80941Smrg   assert(table);
144b8e80941Smrg   mtx_unlock(&table->Mutex);
145b8e80941Smrg}
146848b8605Smrg
147848b8605Smrgextern void *_mesa_HashLookupLocked(struct _mesa_HashTable *table, GLuint key);
148848b8605Smrg
149848b8605Smrgextern void _mesa_HashInsertLocked(struct _mesa_HashTable *table,
150848b8605Smrg                                   GLuint key, void *data);
151848b8605Smrg
152b8e80941Smrgextern void _mesa_HashRemoveLocked(struct _mesa_HashTable *table, GLuint key);
153b8e80941Smrg
154848b8605Smrgextern void
155848b8605Smrg_mesa_HashDeleteAll(struct _mesa_HashTable *table,
156848b8605Smrg                    void (*callback)(GLuint key, void *data, void *userData),
157848b8605Smrg                    void *userData);
158848b8605Smrg
159848b8605Smrgextern void
160848b8605Smrg_mesa_HashWalk(const struct _mesa_HashTable *table,
161848b8605Smrg               void (*callback)(GLuint key, void *data, void *userData),
162848b8605Smrg               void *userData);
163848b8605Smrg
164b8e80941Smrgextern void
165b8e80941Smrg_mesa_HashWalkLocked(const struct _mesa_HashTable *table,
166b8e80941Smrg                     void (*callback)(GLuint key, void *data, void *userData),
167b8e80941Smrg                     void *userData);
168b8e80941Smrg
169848b8605Smrgextern void _mesa_HashPrint(const struct _mesa_HashTable *table);
170848b8605Smrg
171848b8605Smrgextern GLuint _mesa_HashFindFreeKeyBlock(struct _mesa_HashTable *table, GLuint numKeys);
172848b8605Smrg
173848b8605Smrgextern GLuint
174848b8605Smrg_mesa_HashNumEntries(const struct _mesa_HashTable *table);
175848b8605Smrg
176848b8605Smrgextern void _mesa_test_hash_functions(void);
177848b8605Smrg
178848b8605Smrg
179848b8605Smrg#endif
180