Skip to content

Instantly share code, notes, and snippets.

/ws.c

Created January 6, 2013 23:17
Show Gist options
  • Save anonymous/4470980 to your computer and use it in GitHub Desktop.
Save anonymous/4470980 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
// WORKSPACE BEISPIEL
// FreeBsd Lizenziert
// tim glabisch
//
// Ein Workspace ermöglicht, dass beliebige variablen darin abgelegt werden, der komplette
// Workspace kann daraufhin aus dem Ram abgelegt werden.
// Varnish nutzt dies beispielsweise damit in (inline C) Plugins speicherplatz über eine WS_MALLOC
// Methode beschaffen werden kann.
// Varnish hat keine Möglichkeit zu erkennen wann die Variable wieder freigegeben werden kann,
// Die Lösung ist einfach:
// Der Benutzer muss den Speicher aus einem vorab angelegten Workspace beschaffen,
// Dieser Workspace kann nach verarbeitung des Requests gelöscht werden, damit sind Memory-Leaks
// nicht mehr möglich.
//
// Das Beispiel ist mit Valgrind getestet und enthält keine Memory Leaks
//
// Um das Programm zu testen reicht:
// $ gcc -o a.out -g -O0 [FILE].c
// Der Eigentliche Workspace enthält einen Void Pointer damit beliebige Daten abgelegt werden
// können. Desweiteren wird gespeichert wie groß dieser insgesamt ist, sowie wieviel speicher noch
// vorhanden ist
typedef struct {
void* data;
int bytesUsed;
int bytesTotal;
} ws;
// Ein neuer Workspace kann über die Funktion ws_new erstellt werden
// als Parameter wird die Anzahl der bytes übergeben welche für den Workspace beitstehen müssen.
// Dies entspricht der "größe" des Void-Pointers (data) den der Workspace für die Daten
// vorhalten muss
ws* ws_new(int bytes) {
ws* workspace = (ws*)malloc(sizeof(ws));
workspace->data = (void*)malloc(bytes);
workspace->bytesUsed = 0;
workspace->bytesTotal = bytes;
return workspace;
}
// ws_free löscht ein ws Objekt aus dem Speicher
// erst die Daten, dann das eigentliche Objekt
void ws_free(ws* workspace) {
free(workspace->data);
free(workspace);
}
// ws_malloc wird aufgerufen um neuen Speicher aus dem Workspace zu holen.
// dies funktioniert ähnlich wie die eigentliche malloc funktion, der Speicher wird jedoch
// aus dem Workspace geholt. Um Überläufe zu vermeiden muss geprüft werden ob der Workspace groß
// genug ist.
void* ws_malloc(ws* workspace, int bytes) {
if(bytes > workspace->bytesTotal - workspace->bytesUsed)
return NULL;
void* ret = (void*) workspace->data + workspace->bytesUsed;
workspace->bytesUsed = workspace->bytesUsed + bytes;
return ret;
}
int main() {
ws* workspace = ws_new(8);
char* c1 = (char*)ws_malloc(workspace, 4);
strcpy(c1, "abc");
// alloc the first 4 bytes and check if everything works :)
assert(strcmp(c1, "abc") == 0);
char* c2 = (char*)ws_malloc(workspace, 4);
strcpy(c2, "def");
// check the first and the second allocaton
assert(strcmp(c1, "abc") == 0);
assert(strcmp(c2, "def") == 0);
// we just have 8 bytes, no so we couldnt alloc more ...
assert(ws_malloc(workspace, 1) == NULL);
ws_free(workspace);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment