Last active
August 16, 2025 05:20
-
-
Save LowByteFox/a471a1ba23ceb0ddf041ac6ff3eed966 to your computer and use it in GitHub Desktop.
RefCell<T> from Rust in C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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 */ | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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