input: Map the mappings instead of reading them

This makes the operation take 0.5ms, compared to 1ms previously, and
allows the page to be shared with other GLFW programs running
concurrently.
This commit is contained in:
Emmanuel Gil Peyrot 2021-03-23 13:30:12 +01:00
parent 1698fb2af1
commit 6be3ddbf4e
4 changed files with 34 additions and 42 deletions

View File

@ -34,9 +34,11 @@
#error "libxxhash is required for the compose cache" #error "libxxhash is required for the compose cache"
#endif #endif
#include <fcntl.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sys/mman.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#define XXH_INLINE_ALL #define XXH_INLINE_ALL
@ -126,53 +128,30 @@ cacheGetPathFromString(const char *string, char **cachePath)
GLFWbool GLFWbool
cacheRead(const char *path, _GLFWmapping** out, int* count) cacheRead(const char *path, _GLFWmapping** out, int* count)
{ {
FILE *f; int fd;
int length, i; int length;
_GLFWmapping* mappings; void* map;
_GLFWmapping* mapping;
#define FREAD(ptr, size, nmemb, stream) \ fd = open(path, O_RDONLY);
do \ if (fd < 0)
{ \
if (fread(ptr, size, nmemb, stream) < nmemb) \
return GLFW_FALSE; \
} while (0)
#define FREAD_n(ptr, nmemb, stream) \
FREAD(ptr, sizeof(*ptr), nmemb, stream)
#define FREAD_1(value, stream) \
FREAD_n(&value, 1, stream)
f = fopen(path, "rb");
if (!f)
return GLFW_FALSE; return GLFW_FALSE;
FREAD_1(length, f); if (read(fd, &length, 4) != 4)
mappings = malloc(length * sizeof(_GLFWmapping));
if (!mappings)
goto error;
for (i = 0; i < length; ++i)
{ {
mapping = &mappings[i]; close(fd);
FREAD_n(mapping->name, 128, f); return GLFW_FALSE;
FREAD_n(mapping->guid, 16, f);
FREAD_n(mapping->buttons, 15, f);
FREAD_n(mapping->axes, 6, f);
} }
#undef FREAD_1 map = mmap(NULL, 4 + length * sizeof(_GLFWmapping), PROT_READ, MAP_PRIVATE, fd, 0);
#undef FREAD_n if (map == MAP_FAILED)
#undef FREAD {
close(fd);
return GLFW_FALSE;
}
fclose(f);
*count = length; *count = length;
*out = mappings; *out = map + 4;
return GLFW_TRUE; return GLFW_TRUE;
error:
fclose(f);
unlink(path);
return GLFW_FALSE;
} }
void void

View File

@ -36,6 +36,10 @@
#include <stdarg.h> #include <stdarg.h>
#include <assert.h> #include <assert.h>
#ifdef HAVE_XXHASH
#include <sys/mman.h>
#endif
// The global variables below comprise all mutable global data in GLFW // The global variables below comprise all mutable global data in GLFW
// //
@ -86,7 +90,12 @@ static void terminate(void)
_glfw.monitors = NULL; _glfw.monitors = NULL;
_glfw.monitorCount = 0; _glfw.monitorCount = 0;
free(_glfw.mappings); #ifdef HAVE_XXHASH
if (_glfw.mappingMmapped)
munmap((void*)_glfw.mappings - 4, 4 + _glfw.mappingCount * sizeof(_GLFWmapping));
else
#endif
free(_glfw.mappings);
_glfw.mappings = NULL; _glfw.mappings = NULL;
_glfw.mappingCount = 0; _glfw.mappingCount = 0;

View File

@ -1194,7 +1194,7 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
const char* c = string; const char* c = string;
#ifdef HAVE_XXHASH #ifdef HAVE_XXHASH
char *cachePath; char *cachePath;
GLFWbool usableCache, readFromCache = GLFW_FALSE; GLFWbool usableCache;
#endif #endif
assert(string != NULL); assert(string != NULL);
@ -1206,9 +1206,10 @@ GLFWAPI int glfwUpdateGamepadMappings(const char* string)
if (usableCache && cacheRead(cachePath, &_glfw.mappings, &_glfw.mappingCount)) if (usableCache && cacheRead(cachePath, &_glfw.mappings, &_glfw.mappingCount))
{ {
readFromCache = GLFW_TRUE; _glfw.mappingMmapped = GLFW_TRUE;
goto doMapping; goto doMapping;
} }
_glfw.mappingMmapped = GLFW_FALSE;
#endif #endif
while (*c) while (*c)
@ -1264,7 +1265,7 @@ doMapping:
} }
#ifdef HAVE_XXHASH #ifdef HAVE_XXHASH
if (usableCache && !readFromCache) if (usableCache && !_glfw.mappingMmapped)
cacheWrite(cachePath, _glfw.mappings, _glfw.mappingCount); cacheWrite(cachePath, _glfw.mappings, _glfw.mappingCount);
free(cachePath); free(cachePath);

View File

@ -544,6 +544,9 @@ struct _GLFWlibrary
_GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1]; _GLFWjoystick joysticks[GLFW_JOYSTICK_LAST + 1];
_GLFWmapping* mappings; _GLFWmapping* mappings;
int mappingCount; int mappingCount;
#ifdef HAVE_XXHASH
GLFWbool mappingMmapped;
#endif
_GLFWtls errorSlot; _GLFWtls errorSlot;
_GLFWtls contextSlot; _GLFWtls contextSlot;