Skip to content

Instantly share code, notes, and snippets.

@LowByteFox
Last active August 16, 2025 05:20
Show Gist options
  • Select an option

  • Save LowByteFox/a471a1ba23ceb0ddf041ac6ff3eed966 to your computer and use it in GitHub Desktop.

Select an option

Save LowByteFox/a471a1ba23ceb0ddf041ac6ff3eed966 to your computer and use it in GitHub Desktop.
RefCell<T> from Rust in C
#include "refcell.h"
MAKE_REFCELL(int, int);
int main()
{
struct refcell_int ref = make_int_ref(0);
const int *borrow1 = refcell_int_borrow(&ref);
const int *borrow2 = refcell_int_borrow(&ref);
const int *borrow3 = refcell_int_borrow(&ref);
const int *borrow4 = refcell_int_borrow(&ref);
int *mut_borrow = refcell_int_borrow_mut(&ref); /* ded */
}
#ifndef __REFCELL_H__
#define __REFCELL_H__
#include <assert.h>
#include <stdint.h>
#include <unistd.h>
#ifndef NDEBUG
#define MAKE_REFCELL(type, name) \
struct refcell_ ## name { \
ssize_t borrow_count; \
type value; \
}; \
struct refcell_ ## name make_ ## name ## _ref(type value) { \
return (struct refcell_ ## name) { 0, value }; \
} \
const type *refcell_ ## name ## _borrow(struct refcell_ ## name *self) \
refcell_borrow(self, type, name) \
type *refcell_ ## name ## _borrow_mut(struct refcell_ ## name *self) \
refcell_borrow_mut(self, type, name) \
void refcell_ ## name ## _drop(struct refcell_ ## name *self) { \
self->borrow_count--; \
} \
void refcell ## name ## _drop_mut(struct refcell_ ## name *self) { \
self->borrow_count++; \
}
#define refcell_borrow(ref, type, name) { \
assert(self->borrow_count != -1 && "Cannot borrow as immutable because it is also borrowed as mutable");\
self->borrow_count++; \
return &self->value; \
}
#define refcell_borrow_mut(ref, type, name) { \
assert(self->borrow_count <= 0 && "Cannot borrow as mutable because it is also borrowed as immutable"); \
assert(self->borrow_count >= 0 && "Cannot borrow as mutable more than once at a time"); \
self->borrow_count--; \
return &self->value; \
}
#else
#define MAKE_REFCELL(type, name) \
struct refcell_ ## name { \
type value; \
}; \
struct refcell_ ## name make_ ## name ## _ref(type value) { \
return (struct refcell_ ## name) { value }; \
} \
const type *refcell_ ## name ## _borrow(struct refcell_ ## name *self) {\
return &self->value; \
} \
type *refcell_ ## name ## _borrow_mut(struct refcell_ ## name *self) { \
return &self->value; \
} \
void refcell_ ## name ## _drop(struct refcell_ ## name *self) {} \
void refcell ## name ## _drop_mut(struct refcell_ ## name *self) {}
#endif
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment