Path: blob/master/Utilities/cmlibuv/src/win/fs-fd-hash-inl.h
3153 views
/* Copyright libuv project contributors. All rights reserved.1*2* Permission is hereby granted, free of charge, to any person obtaining a copy3* of this software and associated documentation files (the "Software"), to4* deal in the Software without restriction, including without limitation the5* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or6* sell copies of the Software, and to permit persons to whom the Software is7* furnished to do so, subject to the following conditions:8*9* The above copyright notice and this permission notice shall be included in10* all copies or substantial portions of the Software.11*12* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR13* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,14* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE15* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER16* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING17* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS18* IN THE SOFTWARE.19*/2021#ifndef UV_WIN_FS_FD_HASH_INL_H_22#define UV_WIN_FS_FD_HASH_INL_H_2324#include "uv.h"25#include "internal.h"2627/* Files are only inserted in uv__fd_hash when the UV_FS_O_FILEMAP flag is28* specified. Thus, when uv__fd_hash_get returns true, the file mapping in the29* info structure should be used for read/write operations.30*31* If the file is empty, the mapping field will be set to32* INVALID_HANDLE_VALUE. This is not an issue since the file mapping needs to33* be created anyway when the file size changes.34*35* Since file descriptors are sequential integers, the modulo operator is used36* as hashing function. For each bucket, a single linked list of arrays is37* kept to minimize allocations. A statically allocated memory buffer is kept38* for the first array in each bucket. */394041#define UV__FD_HASH_SIZE 25642#define UV__FD_HASH_GROUP_SIZE 164344struct uv__fd_info_s {45int flags;46BOOLEAN is_directory;47HANDLE mapping;48LARGE_INTEGER size;49LARGE_INTEGER current_pos;50};5152struct uv__fd_hash_entry_s {53uv_file fd;54struct uv__fd_info_s info;55};5657struct uv__fd_hash_entry_group_s {58struct uv__fd_hash_entry_s entries[UV__FD_HASH_GROUP_SIZE];59struct uv__fd_hash_entry_group_s* next;60};6162struct uv__fd_hash_bucket_s {63size_t size;64struct uv__fd_hash_entry_group_s* data;65};666768static uv_mutex_t uv__fd_hash_mutex;6970static struct uv__fd_hash_entry_group_s71uv__fd_hash_entry_initial[UV__FD_HASH_SIZE * UV__FD_HASH_GROUP_SIZE];72static struct uv__fd_hash_bucket_s uv__fd_hash[UV__FD_HASH_SIZE];737475INLINE static void uv__fd_hash_init(void) {76size_t i;77int err;7879err = uv_mutex_init(&uv__fd_hash_mutex);80if (err) {81uv_fatal_error(err, "uv_mutex_init");82}8384for (i = 0; i < ARRAY_SIZE(uv__fd_hash); ++i) {85uv__fd_hash[i].size = 0;86uv__fd_hash[i].data =87uv__fd_hash_entry_initial + i * UV__FD_HASH_GROUP_SIZE;88}89}9091#define FIND_COMMON_VARIABLES \92unsigned i; \93unsigned bucket = fd % ARRAY_SIZE(uv__fd_hash); \94struct uv__fd_hash_entry_s* entry_ptr = NULL; \95struct uv__fd_hash_entry_group_s* group_ptr; \96struct uv__fd_hash_bucket_s* bucket_ptr = &uv__fd_hash[bucket];9798#define FIND_IN_GROUP_PTR(group_size) \99do { \100for (i = 0; i < group_size; ++i) { \101if (group_ptr->entries[i].fd == fd) { \102entry_ptr = &group_ptr->entries[i]; \103break; \104} \105} \106} while (0)107108#define FIND_IN_BUCKET_PTR() \109do { \110size_t first_group_size = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE; \111if (bucket_ptr->size != 0 && first_group_size == 0) \112first_group_size = UV__FD_HASH_GROUP_SIZE; \113group_ptr = bucket_ptr->data; \114FIND_IN_GROUP_PTR(first_group_size); \115for (group_ptr = group_ptr->next; \116group_ptr != NULL && entry_ptr == NULL; \117group_ptr = group_ptr->next) \118FIND_IN_GROUP_PTR(UV__FD_HASH_GROUP_SIZE); \119} while (0)120121INLINE static int uv__fd_hash_get(int fd, struct uv__fd_info_s* info) {122FIND_COMMON_VARIABLES123124uv_mutex_lock(&uv__fd_hash_mutex);125126FIND_IN_BUCKET_PTR();127128if (entry_ptr != NULL) {129*info = entry_ptr->info;130}131132uv_mutex_unlock(&uv__fd_hash_mutex);133return entry_ptr != NULL;134}135136INLINE static void uv__fd_hash_add(int fd, struct uv__fd_info_s* info) {137FIND_COMMON_VARIABLES138139uv_mutex_lock(&uv__fd_hash_mutex);140141FIND_IN_BUCKET_PTR();142143if (entry_ptr == NULL) {144i = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE;145146if (bucket_ptr->size != 0 && i == 0) {147struct uv__fd_hash_entry_group_s* new_group_ptr =148uv__malloc(sizeof(*new_group_ptr));149if (new_group_ptr == NULL) {150uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");151}152new_group_ptr->next = bucket_ptr->data;153bucket_ptr->data = new_group_ptr;154}155156bucket_ptr->size += 1;157entry_ptr = &bucket_ptr->data->entries[i];158entry_ptr->fd = fd;159}160161entry_ptr->info = *info;162163uv_mutex_unlock(&uv__fd_hash_mutex);164}165166INLINE static int uv__fd_hash_remove(int fd, struct uv__fd_info_s* info) {167FIND_COMMON_VARIABLES168169uv_mutex_lock(&uv__fd_hash_mutex);170171FIND_IN_BUCKET_PTR();172173if (entry_ptr != NULL) {174*info = entry_ptr->info;175176bucket_ptr->size -= 1;177178i = bucket_ptr->size % UV__FD_HASH_GROUP_SIZE;179if (entry_ptr != &bucket_ptr->data->entries[i]) {180*entry_ptr = bucket_ptr->data->entries[i];181}182183if (bucket_ptr->size != 0 &&184bucket_ptr->size % UV__FD_HASH_GROUP_SIZE == 0) {185struct uv__fd_hash_entry_group_s* old_group_ptr = bucket_ptr->data;186bucket_ptr->data = old_group_ptr->next;187uv__free(old_group_ptr);188}189}190191uv_mutex_unlock(&uv__fd_hash_mutex);192return entry_ptr != NULL;193}194195#undef FIND_COMMON_VARIABLES196#undef FIND_IN_GROUP_PTR197#undef FIND_IN_BUCKET_PTR198199#endif /* UV_WIN_FS_FD_HASH_INL_H_ */200201202