feat: rcmem
This commit is contained in:
@@ -14,6 +14,9 @@ target_include_directories(
|
||||
add_executable(strings ${CMAKE_CURRENT_SOURCE_DIR}/app/strings.c)
|
||||
target_link_libraries(strings PRIVATE c-libs)
|
||||
|
||||
add_executable(rc ${CMAKE_CURRENT_SOURCE_DIR}/app/rc.c)
|
||||
target_link_libraries(rc PRIVATE c-libs)
|
||||
|
||||
include(CTest)
|
||||
if(BUILD_TESTING)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
@@ -30,25 +33,26 @@ endif()
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
install(
|
||||
TARGETS c-libs
|
||||
EXPORT c-libs
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
RUNTIME DESTINATION bin)
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/c-libs
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
install(
|
||||
EXPORT c-libs
|
||||
FILE c-libsTargets.cmake
|
||||
NAMESPACE c-libs::
|
||||
DESTINATION lib/cmake/c-libs)
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/c-libs)
|
||||
|
||||
configure_package_config_file(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/c-libsConfig.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/c-libsConfig.cmake
|
||||
INSTALL_DESTINATION lib/cmake/c-libs)
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/c-libs)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/c-libsConfig.cmake
|
||||
DESTINATION lib/cmake/c-libs)
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/c-libs)
|
||||
|
||||
35
app/rc.c
Normal file
35
app/rc.c
Normal file
@@ -0,0 +1,35 @@
|
||||
#include <c-libs/rcmem.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
void do_stuff(char *rc_s) { printf("Ptr %p -> %s\n", rc_s, rc_s); }
|
||||
|
||||
char *mk_rc_str(const char *s) {
|
||||
char *rc_s = rc_new(20);
|
||||
strncpy(rc_s, s, 20);
|
||||
return rc_s;
|
||||
}
|
||||
|
||||
void rc_info(void *rc) { printf("RC: %d, WRC: %d\n", rc_rc(rc), rc_wrc(rc)); }
|
||||
|
||||
static char *global_rc_s;
|
||||
|
||||
int main() {
|
||||
char *rc_s = mk_rc_str("Hello World!");
|
||||
|
||||
global_rc_s = rc_ref(rc_s);
|
||||
rc_info(rc_s);
|
||||
rc_unref(rc_s);
|
||||
rc_info(global_rc_s);
|
||||
|
||||
do_stuff(global_rc_s);
|
||||
|
||||
global_rc_s = rc_realloc(global_rc_s, 20480);
|
||||
memset(global_rc_s, 'A', 20480);
|
||||
global_rc_s[50] = '\0';
|
||||
do_stuff(global_rc_s);
|
||||
|
||||
rc_unref(global_rc_s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -17,7 +17,9 @@
|
||||
|
||||
flake = {
|
||||
overlays.default = final: prev: {
|
||||
c-libs = final.callPackage ./nix/c-libs.nix {};
|
||||
c-libs = (final.callPackage ./nix/c-libs.nix {}).overrideAttrs {
|
||||
enableShared = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -49,6 +51,8 @@
|
||||
shellHook = ''
|
||||
export CMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||
export BUILD_TESTING=ON
|
||||
export MANPATH="${pkgs.man-pages-posix}/share/man:$MANPATH"
|
||||
export MANPATH="${pkgs.man-pages}/share/man:$MANPATH"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
108
include/c-libs/rcmem.h
Normal file
108
include/c-libs/rcmem.h
Normal file
@@ -0,0 +1,108 @@
|
||||
#ifndef CLIBS_RCMEM_H
|
||||
#define CLIBS_RCMEM_H
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <memory.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t rc;
|
||||
uint32_t wrc;
|
||||
size_t len;
|
||||
} RCHeader;
|
||||
|
||||
void *rc_new(size_t size) {
|
||||
RCHeader *hdr = mmap(NULL, sizeof(RCHeader) + size, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
|
||||
if (hdr == MAP_FAILED) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hdr->rc = 1;
|
||||
hdr->len = size;
|
||||
|
||||
return hdr + 1;
|
||||
}
|
||||
|
||||
void *rc_ref(void *ptr) {
|
||||
RCHeader *hdr = ((RCHeader *)ptr) - 1;
|
||||
hdr->rc += 1;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void *rc_wref(void *ptr) {
|
||||
RCHeader *hdr = ((RCHeader *)ptr) - 1;
|
||||
hdr->wrc += 1;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
uint32_t rc_rc(void *ptr) {
|
||||
RCHeader *hdr = ((RCHeader *)ptr) - 1;
|
||||
|
||||
return hdr->rc;
|
||||
}
|
||||
|
||||
uint32_t rc_wrc(void *ptr) {
|
||||
RCHeader *hdr = ((RCHeader *)ptr) - 1;
|
||||
|
||||
return hdr->wrc;
|
||||
}
|
||||
|
||||
void *rc_clone(void *ptr) {
|
||||
RCHeader *hdr = ((RCHeader *)ptr) - 1;
|
||||
|
||||
size_t len = sizeof(RCHeader) + hdr->len;
|
||||
|
||||
RCHeader *chdr = mmap(NULL, len, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
|
||||
memcpy(chdr, hdr, len);
|
||||
|
||||
return chdr + 1;
|
||||
}
|
||||
|
||||
void *rc_realloc(void *ptr, size_t size) {
|
||||
RCHeader *hdr = ((RCHeader *)ptr) - 1;
|
||||
size_t old_size = sizeof(RCHeader) + hdr->len;
|
||||
size_t new_size = sizeof(RCHeader) + size;
|
||||
|
||||
RCHeader *new = mremap(hdr, old_size, new_size, MREMAP_MAYMOVE);
|
||||
new->len = size;
|
||||
|
||||
if (new == MAP_FAILED) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new + 1;
|
||||
}
|
||||
|
||||
uint32_t rc_wunref(void *ptr) {
|
||||
RCHeader *hdr = ((RCHeader *)ptr) - 1;
|
||||
hdr->wrc -= 1;
|
||||
uint32_t wrc = hdr->wrc;
|
||||
|
||||
if (!hdr->wrc && !hdr->rc) {
|
||||
munmap(hdr, sizeof(RCHeader) + hdr->len);
|
||||
}
|
||||
|
||||
return wrc;
|
||||
}
|
||||
|
||||
uint32_t rc_unref(void *ptr) {
|
||||
RCHeader *hdr = ((RCHeader *)ptr) - 1;
|
||||
hdr->rc -= 1;
|
||||
uint32_t rc = hdr->rc;
|
||||
|
||||
if (!hdr->wrc && !hdr->rc) {
|
||||
munmap(hdr, sizeof(RCHeader) + hdr->len);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -10,12 +10,12 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "c-libs";
|
||||
version = "0.1.0";
|
||||
src = ../.;
|
||||
outputs = ["out" "dev"];
|
||||
nativeBuildInputs = [cmake] ++ lib.optional finalAttrs.doCheck pkg-config;
|
||||
buildInputs = [] ++ lib.optional finalAttrs.doCheck criterion;
|
||||
|
||||
cmakeFlags = [
|
||||
(lib.cmakeBool "BUILD_TESTING" finalAttrs.doCheck)
|
||||
(lib.cmakeBool "BUILD_SHARED_LIBS" finalAttrs.enableShared or false)
|
||||
];
|
||||
|
||||
doCheck = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
|
||||
|
||||
Reference in New Issue
Block a user