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

View File

@ -36,6 +36,10 @@
#include <stdarg.h>
#include <assert.h>
#ifdef HAVE_XXHASH
#include <sys/mman.h>
#endif
// The global variables below comprise all mutable global data in GLFW
//
@ -86,7 +90,12 @@ static void terminate(void)
_glfw.monitors = NULL;
_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.mappingCount = 0;

View File

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

View File

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