mirror of
https://github.com/sigmasternchen/CFloor
synced 2025-03-15 20:28:56 +00:00
linked list implementation
This commit is contained in:
parent
428eec9e61
commit
f576501083
5 changed files with 246 additions and 6 deletions
10
Makefile
10
Makefile
|
@ -1,19 +1,21 @@
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -Wall -Wpedantic
|
CFLAGS = -Wall -Wpedantic
|
||||||
LD = gcc
|
LD = gcc
|
||||||
LDFLAGS =
|
LDFLAGS = -lpthread -lrt
|
||||||
|
|
||||||
BIN_NAME = cfloor
|
BIN_NAME = cfloor
|
||||||
|
|
||||||
all: $(BIN_NAME)
|
all: $(BIN_NAME)
|
||||||
|
|
||||||
test: obj/test.o obj/networking.o
|
test: obj/test.o obj/networking.o obj/linked.o
|
||||||
$(LD) -o $@ $^
|
$(LD) $(LDFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
obj/test.o: src/networking.h
|
||||||
obj/networking.o: src/networking.h src/headers.h
|
obj/networking.o: src/networking.h src/headers.h
|
||||||
|
obj/linked.o: src/linked.h
|
||||||
|
|
||||||
obj/%.o: src/%.c obj
|
obj/%.o: src/%.c obj
|
||||||
$(CC) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
obj:
|
obj:
|
||||||
@mkdir -p obj
|
@mkdir -p obj
|
||||||
|
|
205
src/linked.c
205
src/linked.c
|
@ -0,0 +1,205 @@
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "linked.h"
|
||||||
|
|
||||||
|
linkedList_t linked_create() {
|
||||||
|
linkedList_t list = {
|
||||||
|
.first = NULL
|
||||||
|
};
|
||||||
|
sem_init(&(list.modify_sem), 0, 1);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t linked_push(linkedList_t* list, void* data) {
|
||||||
|
link_t* new = malloc(sizeof (link_t));
|
||||||
|
if (new == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
new->data = data;
|
||||||
|
sem_init(&(new->modify_sem), 0, 1);
|
||||||
|
new->inUse = 0;
|
||||||
|
new->list = list;
|
||||||
|
new->next = NULL;
|
||||||
|
new->unlinked = false;
|
||||||
|
|
||||||
|
size_t index = 0;
|
||||||
|
|
||||||
|
link_t* current = NULL;
|
||||||
|
|
||||||
|
sem_wait(&(list->modify_sem));
|
||||||
|
current = list->first;
|
||||||
|
if (current == NULL) {
|
||||||
|
new->prev = NULL;
|
||||||
|
list->first = new;
|
||||||
|
sem_post(&(list->modify_sem));
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
sem_post(&(list->modify_sem));
|
||||||
|
|
||||||
|
index++;
|
||||||
|
sem_wait(&(current->modify_sem));
|
||||||
|
while(current->next != NULL) {
|
||||||
|
sem_wait(&(current->next->modify_sem));
|
||||||
|
sem_post(&(current->modify_sem));
|
||||||
|
current = current->next;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
new->prev = current;
|
||||||
|
current->next = new;
|
||||||
|
|
||||||
|
sem_post(&(current->modify_sem));
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
link_t* linked_first(linkedList_t* list) {
|
||||||
|
if (list->first == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
link_t* link = list->first;
|
||||||
|
|
||||||
|
link->inUse++;
|
||||||
|
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linked_free(link_t* link) {
|
||||||
|
free(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
void linked_unlock(link_t* link) {
|
||||||
|
link->inUse--;
|
||||||
|
|
||||||
|
if (link->unlinked && link->inUse == 0) {
|
||||||
|
linked_free(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
link_t* linked_next(link_t* link) {
|
||||||
|
linked_unlock(link);
|
||||||
|
|
||||||
|
if (link->next == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
link = link->next;
|
||||||
|
|
||||||
|
link->inUse++;
|
||||||
|
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
link_t* linked_get(linkedList_t* list, size_t index) {
|
||||||
|
link_t* link = linked_first(list);
|
||||||
|
|
||||||
|
while(link != NULL) {
|
||||||
|
if (index-- == 0) {
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
link = linked_next(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t linked_length(linkedList_t* list) {
|
||||||
|
link_t* link = linked_first(list);
|
||||||
|
|
||||||
|
size_t length = 0;
|
||||||
|
|
||||||
|
while(link != NULL) {
|
||||||
|
length++;
|
||||||
|
link = linked_next(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
int linked_unlink(link_t* link) {
|
||||||
|
// need to get prev sem before link sem to avoid dead lock
|
||||||
|
sem_t* prevModify = NULL;
|
||||||
|
link_t** prevNext = NULL;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
/*
|
||||||
|
* Try to lock prev. If locked prev was modified try again.
|
||||||
|
* Abort if link is unlinked.
|
||||||
|
*/
|
||||||
|
|
||||||
|
link_t* prev = link->prev;
|
||||||
|
if (prev == NULL) {
|
||||||
|
sem_wait(&(link->list->modify_sem));
|
||||||
|
if (link->list->first != link) {
|
||||||
|
sem_post(&(link->list->modify_sem));
|
||||||
|
if (link->unlinked) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
prevModify = &(link->list->modify_sem);
|
||||||
|
prevNext = &(link->list->first);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
sem_wait(&(prev->modify_sem));
|
||||||
|
if (prev->next != link) {
|
||||||
|
sem_post(&(prev->modify_sem));
|
||||||
|
if (link->unlinked) {
|
||||||
|
return - 1;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
prevModify = &(prev->modify_sem);
|
||||||
|
prevNext = &(prev->next);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sem_wait(&(link->modify_sem));
|
||||||
|
|
||||||
|
if (link->unlinked) {
|
||||||
|
sem_post(&(link->modify_sem));
|
||||||
|
sem_post(prevModify);
|
||||||
|
return - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link->next) {
|
||||||
|
sem_wait(&(link->next->modify_sem));
|
||||||
|
// we don't need to check for changes because link is already locked
|
||||||
|
|
||||||
|
// while we are here we can modify next
|
||||||
|
link->next->prev = link->prev;
|
||||||
|
|
||||||
|
// we don't need this one anymore
|
||||||
|
sem_post(&(link->next->modify_sem));
|
||||||
|
}
|
||||||
|
|
||||||
|
link->unlinked = true;
|
||||||
|
|
||||||
|
*prevNext = link->next;
|
||||||
|
|
||||||
|
// everything is done
|
||||||
|
|
||||||
|
sem_post(&(link->modify_sem));
|
||||||
|
|
||||||
|
sem_post(prevModify);
|
||||||
|
|
||||||
|
if (link->inUse == 0) {
|
||||||
|
linked_free(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linked_destroy(linkedList_t* list) {
|
||||||
|
link_t* link = linked_first(list);
|
||||||
|
|
||||||
|
while(link != NULL) {
|
||||||
|
link_t* next = link->next;
|
||||||
|
linked_unlink(link);
|
||||||
|
link = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
33
src/linked.h
33
src/linked.h
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef LINKED_H
|
||||||
|
#define LINKED_H
|
||||||
|
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
typedef struct linkedList {
|
||||||
|
sem_t modify_sem;
|
||||||
|
struct link* first;
|
||||||
|
} linkedList_t;
|
||||||
|
|
||||||
|
typedef struct link {
|
||||||
|
void* data;
|
||||||
|
sem_t modify_sem;
|
||||||
|
volatile sig_atomic_t inUse;
|
||||||
|
bool unlinked;
|
||||||
|
struct link* next;
|
||||||
|
struct link* prev;
|
||||||
|
struct linkedList* list;
|
||||||
|
} link_t;
|
||||||
|
|
||||||
|
linkedList_t linked_create();
|
||||||
|
size_t linked_push(linkedList_t* list, void* data);
|
||||||
|
link_t* linked_first(linkedList_t* list);
|
||||||
|
link_t* linked_next(link_t* link);
|
||||||
|
size_t linked_length(linkedList_t* list);
|
||||||
|
void linked_unlock(link_t* link);
|
||||||
|
link_t* linked_get(linkedList_t* list, size_t index);
|
||||||
|
int linked_unlink(link_t* link);
|
||||||
|
void linked_destroy(linkedList_t* list);
|
||||||
|
|
||||||
|
#endif
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char* argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ handler_t handlerGetter(struct metaData metaData, const char* host) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv) {
|
int main(int argc, char** argv) {
|
||||||
initNetworking((struct networkingConfig) {
|
initNetworking((struct networkingConfig) {
|
||||||
.connectionTimeout = 30000,
|
.connectionTimeout = 30000,
|
||||||
.defaultResponse = {
|
.defaultResponse = {
|
||||||
|
|
Loading…
Reference in a new issue