少年修仙传客户端基础资源
hch
2024-04-01 d01413b00ef631ac20347716b23818b0b811f65f
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
/**
 * \file
 * A pointer array that doesn't use reallocs.
 *
 * Copyright (C) 2016 Xamarin Inc
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License 2.0 as published by the Free Software Foundation;
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License 2.0 along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
#ifndef __MONO_SGEN_ARRAY_LIST_H__
#define __MONO_SGEN_ARRAY_LIST_H__
 
#include <glib.h>
 
#define SGEN_ARRAY_LIST_BUCKETS (32)
#define SGEN_ARRAY_LIST_MIN_BUCKET_BITS (5)
#define SGEN_ARRAY_LIST_MIN_BUCKET_SIZE (1 << SGEN_ARRAY_LIST_MIN_BUCKET_BITS)
 
typedef void (*SgenArrayListBucketAllocCallback) (gpointer *bucket, guint32 new_bucket_size, gboolean alloc);
typedef gboolean (*SgenArrayListIsSlotSetFunc) (volatile gpointer *slot);
typedef gboolean (*SgenArrayListSetSlotFunc) (volatile gpointer *slot, gpointer ptr, int data);
 
/*
 * 'entries' is an array of pointers to buckets of increasing size. The first
 * bucket has size 'MIN_BUCKET_SIZE', and each bucket is twice the size of the
 * previous, i.e.:
 *
 *           |-------|-- MIN_BUCKET_SIZE
 *    [0] -> xxxxxxxx
 *    [1] -> xxxxxxxxxxxxxxxx
 *    [2] -> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 *    ...
 *
 * 'slot_hint' denotes the position of the last allocation, so that the
 * whole array needn't be searched on every allocation.
 *
 * The size of the spine, 'SGEN_ARRAY_LIST_BUCKETS', is chosen so
 * that the maximum number of entries is no less than G_MAXUINT32.
 */
 
typedef struct {
    volatile gpointer *volatile entries [SGEN_ARRAY_LIST_BUCKETS];
    volatile guint32 capacity;
    volatile guint32 slot_hint;
    volatile guint32 next_slot;
    SgenArrayListBucketAllocCallback bucket_alloc_callback;
    SgenArrayListIsSlotSetFunc is_slot_set_func;
    SgenArrayListSetSlotFunc set_slot_func;
    int mem_type; /* sgen internal mem type or -1 for malloc allocation */
} SgenArrayList;
 
/*
 * Computes floor(log2(index + MIN_BUCKET_SIZE)) - 1, giving the index
 * of the bucket containing a slot.
 */
static inline guint32
sgen_array_list_index_bucket (guint32 index)
{
#ifdef __GNUC__
    return CHAR_BIT * sizeof (index) - __builtin_clz (index + SGEN_ARRAY_LIST_MIN_BUCKET_SIZE) - 1 - SGEN_ARRAY_LIST_MIN_BUCKET_BITS;
#else
    guint count = 0;
    index += SGEN_ARRAY_LIST_MIN_BUCKET_SIZE;
    while (index) {
        ++count;
        index >>= 1;
    }
    return count - 1 - SGEN_ARRAY_LIST_MIN_BUCKET_BITS;
#endif
}
 
static inline guint32
sgen_array_list_bucket_size (guint32 index)
{
    return 1 << (index + SGEN_ARRAY_LIST_MIN_BUCKET_BITS);
}
 
static inline void
sgen_array_list_bucketize (guint32 index, guint32 *bucket, guint32 *offset)
{
    *bucket = sgen_array_list_index_bucket (index);
    *offset = index - sgen_array_list_bucket_size (*bucket) + SGEN_ARRAY_LIST_MIN_BUCKET_SIZE;
}
 
static inline volatile gpointer *
sgen_array_list_get_slot (SgenArrayList *array, guint32 index)
{
    guint32 bucket, offset;
 
    SGEN_ASSERT (0, index < array->capacity, "Why are we accessing an entry that is not allocated");
 
    sgen_array_list_bucketize (index, &bucket, &offset);
    return &(array->entries [bucket] [offset]);
}
 
#define SGEN_ARRAY_LIST_INIT(bucket_alloc_callback, is_slot_set_func, set_slot_func, mem_type)    { { NULL }, 0, 0, 0, (bucket_alloc_callback), (is_slot_set_func), (set_slot_func), (mem_type) }
 
#define SGEN_ARRAY_LIST_FOREACH_SLOT(array, slot) {            \
    guint32 __bucket, __offset;                    \
    const guint32 __max_bucket = sgen_array_list_index_bucket ((array)->capacity); \
    guint32 __index = 0;                        \
    const guint32 __next_slot = (array)->next_slot;            \
    for (__bucket = 0; __bucket < __max_bucket; ++__bucket) {    \
        volatile gpointer *__entries = (array)->entries [__bucket]; \
        for (__offset = 0; __offset < sgen_array_list_bucket_size (__bucket); ++__offset, ++__index) { \
            if (__index >= __next_slot)            \
                break;                    \
            slot = &__entries [__offset];
 
#define SGEN_ARRAY_LIST_END_FOREACH_SLOT    } } }
 
#define SGEN_ARRAY_LIST_FOREACH_SLOT_RANGE(array, begin, end, slot, index) {    \
    for (index = (begin); index < (end); index++) {        \
        guint32 __bucket, __offset;                \
        volatile gpointer *__entries;                \
        sgen_array_list_bucketize (index, &__bucket, &__offset); \
        __entries = (array)->entries [__bucket];        \
        slot = &__entries [__offset];
 
#define SGEN_ARRAY_LIST_END_FOREACH_SLOT_RANGE    } }
 
guint32 sgen_array_list_alloc_block (SgenArrayList *array, guint32 slots_to_add);
guint32 sgen_array_list_add (SgenArrayList *array, gpointer ptr, int data, gboolean increase_size_before_set);
guint32 sgen_array_list_find (SgenArrayList *array, gpointer ptr);
gboolean sgen_array_list_default_cas_setter (volatile gpointer *slot, gpointer ptr, int data);
gboolean sgen_array_list_default_is_slot_set (volatile gpointer *slot);
void sgen_array_list_remove_nulls (SgenArrayList *array);
 
#endif