Skip to content

Instantly share code, notes, and snippets.

@erikkaplun
Created March 19, 2012 18:03
Show Gist options
  • Save erikkaplun/2121953 to your computer and use it in GitHub Desktop.
Save erikkaplun/2121953 to your computer and use it in GitHub Desktop.
smartpointer (C)
#include <stdio.h>
#include <assert.h>
#define DEBUG
#include "smartasspointer.h"
struct spaceship_t { /* extends */ smartass_t _;
const char* name;
};
spaceship_t* spaceship_new(const char *name)
{
LOG("spaceship_new");
spaceship_t* self = (spaceship_t*) malloc(sizeof(spaceship_t));
smartass_init((smartass_t*) self);
self->name = name;
return self;
}
void spaceship_delete(spaceship_t** self)
{
LOG("spaceship_delete");
smartass_cleanup((smartass_t*) *self);
free(*self);
*self = NULL;
}
typedef struct {
spaceship_t* spaceship;
} missile_t;
missile_t* missile_new(spaceship_t* spaceship)
{
LOG("missile_new");
missile_t* self = (missile_t*) malloc(sizeof(missile_t));
point((void**) &(self->spaceship), spaceship);
return self;
}
void missile_delete(missile_t** self)
{
LOG("missile_delete");
unpoint((void**) &((*self)->spaceship));
free(*self);
*self = NULL;
}
int main()
{
spaceship_t* ss1 = spaceship_new("Spaceship 1");
missile_t* missile1 = missile_new(ss1);
missile_t* missile2 = missile_new(ss1);
missile_t* missile3 = missile_new(ss1);
spaceship_delete(&ss1);
assert(missile1->spaceship == NULL);
assert(missile2->spaceship == NULL);
assert(missile3->spaceship == NULL);
spaceship_t* ss2;
point((void**) &ss2, spaceship_new("Spaceship 2"));
missile_t* missile11 = missile_new(ss2);
missile_t* missile12 = missile_new(ss2);
missile_t* missile13 = missile_new(ss2);
missile_t* missile14 = missile_new(ss2);
missile_t* missile15 = missile_new(ss2);
unpoint((void**) &ss2);
missile_delete(&missile11);
missile_delete(&missile12);
missile_delete(&missile13);
missile_delete(&missile14);
spaceship_t* ss2_ptr;
point((void**) &ss2_ptr, missile15->spaceship);
missile_delete(&missile15);
unpoint((void**) &ss2_ptr);
}
#include <stdio.h>
#include <assert.h>
#define DEBUG
#include "smartasspointer.h"
#define MAGIC_NR 100
void smartass_init(smartass_t* self)
{
LOG("smartass_init");
self->numptrs = 0;
self->ptrs = (void***) malloc(MAGIC_NR * sizeof(void**)); // fuck it
self->tail = self->ptrs;
}
void smartass_cleanup(smartass_t* self)
{
LOG("smartass_cleanup");
for (uint i = 0; i < MAGIC_NR; i += 1) {
if (self->ptrs[i] != NULL) {
LOG("found pointer to smartass");
*self->ptrs[i] = NULL;
self->ptrs[i] = NULL;
}
}
}
void point(void** ptr, void* obj)
{
LOG("point");
smartass_t* smartass = (smartass_t*) obj;
*(smartass->tail) = ptr;
*ptr = obj;
smartass->tail += 1;
smartass->numptrs += 1;
}
void unpoint(void** ptr)
{
LOG("unpoint");
smartass_t* smartass = (smartass_t*) *ptr;
int found = 0;
for (int i = 0; i < MAGIC_NR; i += 1) {
if (smartass->ptrs[i] == ptr) {
smartass->ptrs[i] = NULL;
smartass->numptrs -= 1;
found = 1;
LOG("removing pointer to smartass");
break;
}
}
assert(found == 1);
if (smartass->numptrs == 0) {
LOG("setting smartass free");
free(smartass);
}
*ptr = NULL;
}
#ifndef __SMARTASSPOINTER_H__
#define __SMARTASSPOINTER_H__
typedef unsigned int uint;
#ifdef DEBUG
#define IS_DEBUG 1
#else
#define IS_DEBUG 0
#endif
#define LOG(x) if (IS_DEBUG) { puts(x); }
typedef struct {
uint numptrs;
void*** tail;
void*** ptrs;
} smartass_t;
void smartass_init(smartass_t* self);
void smartass_cleanup(smartass_t* self);
void point(void** ptr, void* obj);
void unpoint(void** ptr);
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment