diff options
author | pancake <pancake@dazo> | 2008-03-05 18:38:42 +0100 |
---|---|---|
committer | pancake <pancake@dazo> | 2008-03-05 18:38:42 +0100 |
commit | 2ddb2923c68d023f9733fb82bb8d28140ea5b695 (patch) | |
tree | 706162ce4107ec1444870ad4945a9e6d5a0cde91 /src/squeue | |
parent | 32a59f4279e1d72abc2b60f08d6e32e2a0b32478 (diff) | |
download | 0xFFFF-2ddb2923c68d023f9733fb82bb8d28140ea5b695.tar.bz2 |
* Initial import of the GtkAML gui frontend - Mostly implemented in just one night :)
* Import the squeue c and vapi sources
* Make 0xFFFF run as squeue daemon with -Q flag
* Up to 0.4
Diffstat (limited to 'src/squeue')
-rw-r--r-- | src/squeue/squeue.c | 250 | ||||
-rw-r--r-- | src/squeue/squeue.h | 27 | ||||
-rw-r--r-- | src/squeue/squeue.vapi | 43 |
3 files changed, 320 insertions, 0 deletions
diff --git a/src/squeue/squeue.c b/src/squeue/squeue.c new file mode 100644 index 0000000..0386784 --- /dev/null +++ b/src/squeue/squeue.c @@ -0,0 +1,250 @@ +#include "squeue.h" +#include <unistd.h> +#include <stdlib.h> +#include <sys/ipc.h> +#include <signal.h> +#include <sys/shm.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> + +#define POOL_SIZE ITEM_MAX*ITEM_SIZE +#define ITEM_SIZE 80 +#define ITEM_MAX 10 + +int squeue_release(const char *file) +{ + int shmid; + key_t k = ftok(file, 0xa3); + + if (k == -1) { + perror("ftok"); + return -1; + } + + shmid = shmget(k, POOL_SIZE, 0666); + if (shmid == -1) + return -1; // not released + return shmctl(shmid, IPC_RMID,NULL); +} + +struct squeue_t *squeue_open(const char *file, int mode) +{ + struct squeue_t *q; + char *pool; + int shmid; + key_t k = ftok(file, 0xa3); +_retry: + shmid = shmget(k, POOL_SIZE, 0666); + if (shmid == -1) { + if (mode == Q_WAIT) { + usleep(200); + goto _retry; + } + shmid = shmget(k, POOL_SIZE, 0666|IPC_EXCL|((mode==Q_CREAT)?IPC_CREAT:0)); + if (shmid == -1) { + if (mode == Q_WAIT) { + usleep(200); + goto _retry; + } + perror("shmget"); + return NULL; + } + } + + if (mode == Q_WAIT) + mode = Q_OPEN; + + pool = shmat(shmid, NULL, k); + if (((int)pool) == -1) { + perror("shmat\n"); + return NULL; + } + + if (mode == Q_CREAT) + memset(pool, '\0', POOL_SIZE); + + q = (struct squeue_t *)malloc(sizeof(struct squeue_t)); + memset(q, '\0', sizeof(struct squeue_t)); + q->shmid = shmid; + q->pool = pool; + q->mode = mode; + + return q; +} + +void squeue_free(struct squeue_t *q) +{ + free(q); +} + +int squeue_close(struct squeue_t *q) +{ + char *pool; + + if (q==NULL) + return -1; + + pool = q->pool; + shmctl(q->shmid, IPC_RMID, NULL); + free(q); + return shmdt(pool); +} + +int squeue_push(struct squeue_t *q, const char *str, int lock) +{ + int i; + + if (q==NULL) + return -1; +// if (q->mode == Q_CREAT) { +// printf("squeue_push: cannot push from the creator\n"); +// return -1; +// } + + if (str==NULL||strlen(str)>ITEM_SIZE) + return -1; + do { + if (q->squeue_idx >= ITEM_MAX) { + while (q->pool[0]!='\0') { + q->squeue_locks++; + if (!lock) { + printf("buffer is full\n"); + return -1; + } + usleep(200); + } + q->squeue_idx = 0; + } + + for(i=q->squeue_idx*ITEM_SIZE;i<POOL_SIZE;i+=ITEM_SIZE) { + if (q->pool[i]=='\0') { + strcpy(q->pool+i, str); + q->squeue_idx++; + return 1; + } + } + q->squeue_locks++; + } while (lock); + q->squeue_lost++; + + return 0; +} + +int squeue_pop(struct squeue_t *q) +{ + int i; + int two = 1; + + if (q==NULL) + return -1; +// if (q->mode == Q_OPEN) { // cannot pop when not owner of squeue +// fprintf(stderr, "squeue_pop: cannot pop when you are not owner.\n"); +// return -1; +// } + for(two=1;two--;q->head_idx = 0) + for(i=q->head_idx*ITEM_SIZE;i<POOL_SIZE;i+=ITEM_SIZE) { + if (q->pool[i]!='\0') { + q->pool[i]='\0'; + q->head_idx++; + q->squeue_pops++; + return 1; + } + } + q->squeue_oops++; + fprintf(stderr, "WARNING: race condition detected in squeue.\n"); + return 0; +} + +char *squeue_get(struct squeue_t *q, int lock) +{ + int i=0; + int two = 1; + + if(q==NULL) + return NULL; +// if (q->mode == Q_OPEN) { // cannot pop when not owner of squeue +// fprintf(stderr, "squeue_get: cannot pop when you are not owner.\n"); +// return NULL; +// } + do { + for(two=1;two--;q->head_idx = 0) { + for(i=q->head_idx*ITEM_SIZE;i<POOL_SIZE;i+=ITEM_SIZE) + if (q->pool[i]!='\0') + return q->pool+i; + } + if (lock) + usleep(500); + } while (lock); + return NULL; +} + +void squeue_stats(struct squeue_t *q) +{ + if(q==NULL) + return; + printf("Queue locks: %d\n", q->squeue_locks); + printf("Queue lost: %d\n", q->squeue_lost); + printf("Queue oops: %d\n", q->squeue_oops); + printf("Queue pops: %d\n", q->squeue_pops); +} + +#if _MAIN_ +struct squeue_t *q; + +int sigc() +{ + squeue_stats(q); + exit(1); +} + +int main() +{ + char buf[102]; + int i; + int pid; + + signal(SIGINT, sigc); + + squeue_release("/dev/null"); + + pid = fork(); + if (pid) { + q = squeue_open("/dev/null", Q_CREAT); + if (q == NULL) { + perror("oops"); + kill(pid, SIGINT); + return; + } + squeue_push(q, "Hello World", 0); + squeue_push(q, "jeje msg 2", 0); + + while(1) { + char *uh = squeue_get(q,1); + if (uh) { + printf("get: (%s)\n", uh); + squeue_pop(q); + } + usleep(200); + } + squeue_close(q); + } else { + q = squeue_open("/dev/null", Q_WAIT); + if (q == NULL) { + perror("oops"); + return; + } + for(i=0;i<128;i++) { + sprintf(buf, "puta%d", i); + squeue_push(q, buf, 1); + usleep(100); + } + squeue_stats(q); + printf("cya\n"); + squeue_close(q); + } + + return 0; +} +#endif diff --git a/src/squeue/squeue.h b/src/squeue/squeue.h new file mode 100644 index 0000000..4730e3d --- /dev/null +++ b/src/squeue/squeue.h @@ -0,0 +1,27 @@ +struct squeue_t { + int shmid; + int mode; + char *pool; + /* pointers */ + int head_idx; + int squeue_idx; + /* counters */ + int squeue_locks; + int squeue_lost; + int squeue_oops; + int squeue_pops; +}; + + +#define Q_OPEN 0 +#define Q_CREAT 1 +#define Q_WAIT 2 + +int squeue_release(const char *file); +struct squeue_t *squeue_open(const char *file, int init); +int squeue_close(struct squeue_t *q); +void squeue_free(struct squeue_t *q); +int squeue_push(struct squeue_t *q, const char *str, int lock); +int squeue_pop(struct squeue_t *q); +char *squeue_get(struct squeue_t *q, int lock); +void squeue_stats(struct squeue_t *q); diff --git a/src/squeue/squeue.vapi b/src/squeue/squeue.vapi new file mode 100644 index 0000000..b8d82d4 --- /dev/null +++ b/src/squeue/squeue.vapi @@ -0,0 +1,43 @@ +using GLib; + +[CCode (lower_case_cprefix = "squeue_", cheader_filename = "squeue.h")] +namespace SQueues { + [CCode (cname = "struct squeue_t", free_function = "squeue_free")] + public struct SQueue { + int shmid; + int mode; + char *pool; + /* pointers */ + int head_idx; + int queue_idx; + /* counters */ + int locks; + int lost; + int oops; + int pops; + [CCode (cname = "squeue_open")] + public static SQueue* open(string file, int mode); + [CCode (cname = "squeue_push")] + public int push(string msg, int l); + [CCode (cname = "squeue_get")] + public weak string get(int l); + [CCode (cname = "squeue_pop")] + public int pop(); + [CCode (cname = "squeue_stats")] + public int stats(); + [CCode (cname = "squeue_close")] + public int close(); + [CCode (cname = "squeue_free")] + public int free(); + [CCode (cname = "squeue_release")] + public static int release(string file); + + } + + [CCode (cprefix = "Q_", cheader_fileneme = "squeue.h")] + public enum SQueueMode { + OPEN = 0, + CREAT = 1, + WAIT = 2 + } +} |