Returns a valid lvalue pointer to the element number 'idx'. Allocates memory if necessary. */
| 96 | Allocates memory if necessary. |
| 97 | */ |
| 98 | void *_lf_dynarray_lvalue(LF_DYNARRAY *array, uint idx) |
| 99 | { |
| 100 | void * ptr, * volatile * ptr_ptr= 0; |
| 101 | int i; |
| 102 | |
| 103 | for (i= LF_DYNARRAY_LEVELS-1; idx < dynarray_idxes_in_prev_levels[i]; i--) |
| 104 | /* no-op */; |
| 105 | ptr_ptr= &array->level[i]; |
| 106 | idx-= dynarray_idxes_in_prev_levels[i]; |
| 107 | for (; i > 0; i--) |
| 108 | { |
| 109 | if (!(ptr= *ptr_ptr)) |
| 110 | { |
| 111 | void *alloc= my_malloc(LF_DYNARRAY_LEVEL_LENGTH * sizeof(void *), |
| 112 | MYF(MY_WME|MY_ZEROFILL)); |
| 113 | if (unlikely(!alloc)) |
| 114 | return(NULL); |
| 115 | if (my_atomic_casptr(ptr_ptr, &ptr, alloc)) |
| 116 | ptr= alloc; |
| 117 | else |
| 118 | my_free(alloc); |
| 119 | } |
| 120 | ptr_ptr= ((void **)ptr) + idx / dynarray_idxes_in_prev_level[i]; |
| 121 | idx%= dynarray_idxes_in_prev_level[i]; |
| 122 | } |
| 123 | if (!(ptr= *ptr_ptr)) |
| 124 | { |
| 125 | uchar *alloc, *data; |
| 126 | alloc= my_malloc(LF_DYNARRAY_LEVEL_LENGTH * array->size_of_element + |
| 127 | MY_MAX(array->size_of_element, sizeof(void *)), |
| 128 | MYF(MY_WME|MY_ZEROFILL)); |
| 129 | if (unlikely(!alloc)) |
| 130 | return(NULL); |
| 131 | /* reserve the space for free() address */ |
| 132 | data= alloc + sizeof(void *); |
| 133 | { /* alignment */ |
| 134 | intptr mod= ((intptr)data) % array->size_of_element; |
| 135 | if (mod) |
| 136 | data+= array->size_of_element - mod; |
| 137 | } |
| 138 | ((void **)data)[-1]= alloc; /* free() will need the original pointer */ |
| 139 | if (my_atomic_casptr(ptr_ptr, &ptr, data)) |
| 140 | ptr= data; |
| 141 | else |
| 142 | my_free(alloc); |
| 143 | } |
| 144 | return ((uchar*)ptr) + array->size_of_element * idx; |
| 145 | } |
| 146 | |
| 147 | /* |
| 148 | Returns a pointer to the element number 'idx' |
no test coverage detected