Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Selene/src/SelFIFO.c
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
201 lines (166 sloc)
4.61 KB
This file contains 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
| /* SelQueue.c | |
| * | |
| * Versatile FIFO queue | |
| * | |
| * 17/06/2017 LF : First version | |
| */ | |
| #include "SelFIFO.h" | |
| #include <assert.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| static struct SelFIFO *firstFifo = NULL; | |
| static struct SelFIFO **checkSelFIFO(lua_State *L){ | |
| void *r = luaL_checkudata(L, 1, "SelFIFO"); | |
| luaL_argcheck(L, r != NULL, 1, "'SelFIFO' expected"); | |
| return (struct SelFIFO **)r; | |
| } | |
| static int sff_create(lua_State *L){ | |
| struct SelFIFO **q = lua_newuserdata(L, sizeof(struct SelFIFO *)); | |
| assert(q); | |
| luaL_getmetatable(L, "SelFIFO"); | |
| lua_setmetatable(L, -2); | |
| assert(*q = malloc(sizeof(struct SelFIFO))); | |
| const char *n = luaL_checkstring(L, 1); /* Name of the Fifo */ | |
| (*q)->h = hash(n); | |
| assert((*q)->name = strdup(n)); | |
| (*q)->next = firstFifo; | |
| firstFifo = *q; | |
| (*q)->first = (*q)->last = NULL; | |
| pthread_mutex_init( &((*q)->mutex), NULL); | |
| return 1; | |
| } | |
| static int sff_find(lua_State *L){ | |
| const char *n = luaL_checkstring(L, 1); /* Name of the Fifo */ | |
| int h = hash(n); | |
| for(struct SelFIFO *p = firstFifo; p; p=p->next) | |
| if( h == p->h && !strcmp(n, p->name) ){ | |
| struct SelFIFO **q = lua_newuserdata(L,sizeof(struct SelFIFO **)); | |
| assert(q); | |
| *q = p; | |
| luaL_getmetatable(L, "SelFIFO"); | |
| lua_setmetatable(L, -2); | |
| return 1; | |
| } | |
| return 0; | |
| } | |
| static int sff_pop(lua_State *L){ | |
| struct SelFIFO *q = *checkSelFIFO(L); | |
| struct SelFIFOCItem *it; | |
| pthread_mutex_lock(&q->mutex); /* Ensure no list modification */ | |
| if(!(it = q->first)){ /* Empty queue */ | |
| pthread_mutex_unlock(&q->mutex); /* Release the list */ | |
| return 0; | |
| } | |
| q->first = it->next; | |
| if(!q->first) /* It was the last one */ | |
| q->last = NULL; | |
| pthread_mutex_unlock(&q->mutex); /* Release the list */ | |
| if( it->type == LUA_TNUMBER ) | |
| lua_pushnumber(L, it->data.n); | |
| else { | |
| lua_pushstring(L, it->data.s); | |
| free(it->data.s); | |
| } | |
| lua_pushnumber(L, it->userdt); | |
| free(it); | |
| return 2; | |
| } | |
| static int sff_push(lua_State *L){ | |
| struct SelFIFO *q = *checkSelFIFO(L); | |
| struct SelFIFOCItem *it = (struct SelFIFOCItem *)malloc( sizeof(struct SelFIFOCItem) ); | |
| if(!it){ | |
| lua_pushnil(L); | |
| lua_pushstring(L, "SelFIFO:Push() - Runing out of memory"); | |
| #ifdef DEBUG | |
| puts("*E* SelFIFO:Push() - Runing out of memory"); | |
| #endif | |
| return 2; | |
| } | |
| it->next = NULL; | |
| if( lua_type(L, 2) == LUA_TNUMBER ){ | |
| it->type = LUA_TNUMBER; | |
| it->data.n = lua_tonumber(L, 2); | |
| } else if( lua_type(L, 2) == LUA_TSTRING ){ | |
| it->type = LUA_TSTRING; | |
| it->data.s = strdup( lua_tostring(L, 2) ); | |
| if(!it->data.s){ | |
| lua_pushnil(L); | |
| lua_pushstring(L, "SelFIFO:Push() - Runing out of memory"); | |
| #ifdef DEBUG | |
| puts("*E* SelFIFO:Push() - Runing out of memory"); | |
| #endif | |
| free(it); | |
| return 2; | |
| } | |
| } else { | |
| lua_pushnil(L); | |
| lua_pushstring(L, "Only Numbers and Strings can be queued"); | |
| #ifdef DEBUG | |
| puts("*E* Only Numbers and Strings can be queued"); | |
| #endif | |
| free(it); | |
| return 2; | |
| } | |
| /* optional user data */ | |
| if( lua_type(L, 3) == LUA_TNUMBER ) | |
| it->userdt = (int)lua_tonumber(L, 3); | |
| else if( lua_type(L, 3) == LUA_TBOOLEAN ) | |
| it->userdt = (int)lua_toboolean(L,3); | |
| else | |
| it->userdt = 0; | |
| pthread_mutex_lock(&q->mutex); | |
| /* Inserting the new data */ | |
| if(q->last){ | |
| q->last->next = it; | |
| q->last = it; | |
| } else { /* First one */ | |
| q->first = q->last = it; | |
| } | |
| pthread_mutex_unlock(&q->mutex); | |
| return 0; | |
| } | |
| static int sff_dump(lua_State *L){ | |
| struct SelFIFO *q = *checkSelFIFO(L); | |
| pthread_mutex_lock(&q->mutex); /* Ensure no list modification */ | |
| printf("SelFIFO '%s'(%d) Dump (first: %p, last: %p)\n", q->name, q->h, q->first, q->last); | |
| for( struct SelFIFOCItem *it = q->first; it; it = it->next ){ | |
| printf("\t%p : ", it); | |
| if( it->type == LUA_TNUMBER ) | |
| printf("(number) %lf", it->data.n); | |
| else if( it->type == LUA_TSTRING ) | |
| printf("(string) '%s'", it->data.s); | |
| else | |
| printf("(unknown type) %d", it->type); | |
| printf(" udt:%d n:%p\n", it->userdt, it->next); | |
| } | |
| pthread_mutex_unlock(&q->mutex); /* Release the list */ | |
| return 0; | |
| } | |
| static int sff_list(lua_State *L){ | |
| puts("SelFIFO's list"); | |
| for(struct SelFIFO *p = firstFifo; p; p=p->next) | |
| printf("\t%p '%s'(%d)\n", p, p->name, p->h); | |
| return 0; | |
| } | |
| static const struct luaL_reg SelFFLib [] = { | |
| {"Create", sff_create}, | |
| {"Find", sff_find}, | |
| {"Push2FIFO", sff_push}, | |
| {NULL, NULL} | |
| }; | |
| static const struct luaL_reg SelFFM [] = { | |
| {"Push", sff_push}, | |
| {"Pop", sff_pop}, | |
| /* {"HowMany", sff_HowMany}, */ | |
| {"dump", sff_dump}, | |
| {"list", sff_list}, | |
| {NULL, NULL} | |
| }; | |
| void init_SelFIFO( lua_State *L ){ /* CAUTION : called also when thread are created */ | |
| luaL_newmetatable(L, "SelFIFO"); | |
| lua_pushstring(L, "__index"); | |
| lua_pushvalue(L, -2); | |
| lua_settable(L, -3); /* metatable.__index = metatable */ | |
| luaL_register(L, NULL, SelFFM); | |
| luaL_register(L,"SelFIFO", SelFFLib); | |
| } | |