feat: rcmem
This commit is contained in:
@@ -14,6 +14,9 @@ target_include_directories(
|
|||||||
add_executable(strings ${CMAKE_CURRENT_SOURCE_DIR}/app/strings.c)
|
add_executable(strings ${CMAKE_CURRENT_SOURCE_DIR}/app/strings.c)
|
||||||
target_link_libraries(strings PRIVATE c-libs)
|
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)
|
include(CTest)
|
||||||
if(BUILD_TESTING)
|
if(BUILD_TESTING)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
@@ -30,25 +33,26 @@ endif()
|
|||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
|
||||||
|
|
||||||
install(
|
install(
|
||||||
TARGETS c-libs
|
TARGETS c-libs
|
||||||
EXPORT c-libs
|
EXPORT c-libs
|
||||||
ARCHIVE DESTINATION lib
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
RUNTIME DESTINATION bin)
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
|
|
||||||
|
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/c-libs
|
||||||
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
|
|
||||||
install(
|
install(
|
||||||
EXPORT c-libs
|
EXPORT c-libs
|
||||||
FILE c-libsTargets.cmake
|
FILE c-libsTargets.cmake
|
||||||
NAMESPACE c-libs::
|
NAMESPACE c-libs::
|
||||||
DESTINATION lib/cmake/c-libs)
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/c-libs)
|
||||||
|
|
||||||
configure_package_config_file(
|
configure_package_config_file(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/c-libsConfig.cmake.in
|
${CMAKE_CURRENT_SOURCE_DIR}/c-libsConfig.cmake.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/c-libsConfig.cmake
|
${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
|
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 = {
|
flake = {
|
||||||
overlays.default = final: prev: {
|
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 = ''
|
shellHook = ''
|
||||||
export CMAKE_EXPORT_COMPILE_COMMANDS=ON
|
export CMAKE_EXPORT_COMPILE_COMMANDS=ON
|
||||||
export BUILD_TESTING=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";
|
pname = "c-libs";
|
||||||
version = "0.1.0";
|
version = "0.1.0";
|
||||||
src = ../.;
|
src = ../.;
|
||||||
outputs = ["out" "dev"];
|
|
||||||
nativeBuildInputs = [cmake] ++ lib.optional finalAttrs.doCheck pkg-config;
|
nativeBuildInputs = [cmake] ++ lib.optional finalAttrs.doCheck pkg-config;
|
||||||
buildInputs = [] ++ lib.optional finalAttrs.doCheck criterion;
|
buildInputs = [] ++ lib.optional finalAttrs.doCheck criterion;
|
||||||
|
|
||||||
cmakeFlags = [
|
cmakeFlags = [
|
||||||
(lib.cmakeBool "BUILD_TESTING" finalAttrs.doCheck)
|
(lib.cmakeBool "BUILD_TESTING" finalAttrs.doCheck)
|
||||||
|
(lib.cmakeBool "BUILD_SHARED_LIBS" finalAttrs.enableShared or false)
|
||||||
];
|
];
|
||||||
|
|
||||||
doCheck = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
|
doCheck = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
|
||||||
|
|||||||
Reference in New Issue
Block a user