Skip to content

Commit

Permalink
Add noheap flag
Browse files Browse the repository at this point in the history
  • Loading branch information
tidwall committed Dec 29, 2024
1 parent 576a61e commit a2b29f1
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 11 deletions.
30 changes: 30 additions & 0 deletions tests/test_various.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,41 @@ void test_various_imported_tests() {
// assert(tg_geom_intersects(b, a) == true);
}

void tg_geom_setnoheap(struct tg_geom *geom);

void test_various_noheap(void) {
struct tg_geom *g1 = tg_parse("POINT(1 1)", 10);
struct tg_geom *g2 = tg_geom_clone(g1);


size_t size = tg_geom_memsize(g1);
struct tg_geom *g3 = alloca(size);
memcpy(g3, g1, size);
tg_geom_setnoheap(g3);
struct tg_geom *g4 = tg_geom_clone(g3);


assert(tg_geom_equals(g1, g2));
assert(tg_geom_equals(g2, g3));
assert(tg_geom_equals(g3, g4));

assert(g1 == g2);
assert(g2 != g3);
assert(g3 != g4);

tg_geom_free(g4);
tg_geom_free(g3);
tg_geom_free(g2);
tg_geom_free(g1);

}

int main(int argc, char **argv) {
do_test(test_various_imported_tests);
do_test(test_various_issue_14);
do_test(test_various_issue_369);
do_test(test_various_unit_tests);
do_test(test_various_noheap);
return 0;
}

Expand Down
38 changes: 27 additions & 11 deletions tg.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,9 @@ static void rc_add(rc_t *rc) {

struct head {
rc_t rc;
enum base base:8;
enum tg_geom_type type:8;
bool noheap;
enum base base:4;
enum tg_geom_type type:4;
enum flags flags:8;
};

Expand Down Expand Up @@ -1835,8 +1836,7 @@ struct tg_ring *tg_ring_new_ix(const struct tg_point *points, int npoints,
/// @param ring Input ring
/// @see RingFuncs
void tg_ring_free(struct tg_ring *ring) {
if (!ring) return;
if (rc_sub(&ring->head.rc)) return;
if (!ring || ring->head.noheap || rc_sub(&ring->head.rc)) return;
if (ring->ystripes) tg_free(ring->ystripes);
tg_free(ring);
}
Expand All @@ -1859,7 +1859,9 @@ static size_t ring_alloc_size(const struct tg_ring *ring) {
/// reference counter.
/// @see RingFuncs
struct tg_ring *tg_ring_clone(const struct tg_ring *ring) {
if (!ring) return NULL;
if (!ring || ring->head.noheap) {
return tg_ring_copy(ring);
}
struct tg_ring *ring_mut = (struct tg_ring*)ring;
rc_add(&ring_mut->head.rc);
return ring_mut;
Expand Down Expand Up @@ -3352,7 +3354,7 @@ void tg_poly_free(struct tg_poly *poly) {
tg_ring_free((struct tg_ring*)poly);
return;
}
if (rc_sub(&poly->head.rc)) return;
if (poly->head.noheap || rc_sub(&poly->head.rc)) return;
if (poly->exterior) tg_ring_free(poly->exterior);
if (poly->holes) {
for (int i = 0; i < poly->nholes; i++) {
Expand All @@ -3371,13 +3373,14 @@ void tg_poly_free(struct tg_poly *poly) {
/// reference counter.
/// @see PolyFuncs
struct tg_poly *tg_poly_clone(const struct tg_poly *poly) {
if (!poly) return NULL;
if (!poly || poly->head.noheap) {
return tg_poly_copy(poly);
}
struct tg_poly *poly_mut = (struct tg_poly*)poly;
rc_add(&poly_mut->head.rc);
return poly_mut;
}


/// Returns the exterior ring.
/// @param poly Input polygon
/// @return Exterior ring
Expand Down Expand Up @@ -3868,7 +3871,7 @@ struct tg_geom *tg_geom_new_point(struct tg_point point) {
}

static void boxed_point_free(struct boxed_point *point) {
if (rc_sub(&point->head.rc)) return;
if (point->head.noheap || rc_sub(&point->head.rc)) return;
tg_free(point);
}

Expand Down Expand Up @@ -4618,14 +4621,16 @@ struct tg_geom *tg_geom_new_multipolygon_zm(
/// reference counter.
/// @see GeometryConstructors
struct tg_geom *tg_geom_clone(const struct tg_geom *geom) {
if (!geom) return NULL;
if (!geom || geom->head.noheap) {
return tg_geom_copy(geom);
}
struct tg_geom *geom_mut = (struct tg_geom*)geom;
rc_add(&geom_mut->head.rc);
return geom_mut;
}

static void geom_free(struct tg_geom *geom) {
if (rc_sub(&geom->head.rc)) return;
if (geom->head.noheap || rc_sub(&geom->head.rc)) return;
switch (geom->head.type) {
case TG_POINT:
break;
Expand Down Expand Up @@ -14002,6 +14007,7 @@ struct tg_ring *tg_ring_copy(const struct tg_ring *ring) {
}
memcpy(ring2, ring, size);
ring2->head.rc = 0;
ring2->head.noheap = 0;
if (ring->ystripes) {
ring2->ystripes = tg_malloc(ring->ystripes->memsz);
if (!ring2->ystripes) {
Expand Down Expand Up @@ -14045,6 +14051,7 @@ struct tg_poly *tg_poly_copy(const struct tg_poly *poly) {
memset(poly2, 0, sizeof(struct tg_poly));
memcpy(&poly2->head, &poly->head, sizeof(struct head));
poly2->head.rc = 0;
poly2->head.noheap = 0;
poly2->exterior = tg_ring_copy(poly->exterior);
if (!poly2->exterior) {
goto fail;
Expand Down Expand Up @@ -14077,6 +14084,7 @@ static struct tg_geom *geom_copy(const struct tg_geom *geom) {
memset(geom2, 0, sizeof(struct tg_geom));
memcpy(&geom2->head, &geom->head, sizeof(struct head));
geom2->head.rc = 0;
geom2->head.noheap = 0;
switch (geom->head.type) {
case TG_POINT:
geom2->point.x = geom->point.x;
Expand Down Expand Up @@ -14173,6 +14181,7 @@ static struct boxed_point *boxed_point_copy(const struct boxed_point *point) {
}
memcpy(point2, point, sizeof(struct boxed_point));
point2->head.rc = 0;
point2->head.noheap = 0;
return point2;
}

Expand Down Expand Up @@ -14361,3 +14370,10 @@ struct tg_geom *tg_parse_ix(const void *data, size_t len, enum tg_index ix) {
struct tg_geom *tg_geom_new_error(const char *error) {
return error?make_parse_error("%s", error):0;
}

/// Set the noheap property to true and the reference counter to zero.
/// _undocumented_
void tg_geom_setnoheap(struct tg_geom *geom) {
geom->head.rc = 0;
geom->head.noheap = 1;
}

0 comments on commit a2b29f1

Please sign in to comment.