WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * A circular queue that can be accessed across fork(). 00006 */ 00007 #include "wvmagiccircle.h" 00008 #include <assert.h> 00009 00010 00011 WvMagicCircle::WvMagicCircle(size_t _size) 00012 : shm(_size + 1 + 2*sizeof(int)), 00013 head(((int*)shm.buf)[0]), tail(((int*)shm.buf)[1]) 00014 { 00015 assert((int)_size > 0); 00016 00017 head = tail = 0; 00018 size = _size + 1; // a circular queue uses one extra byte 00019 circle = shm.cbuf + 2*sizeof(int); 00020 00021 if (shm.geterr()) 00022 seterr(shm); 00023 } 00024 00025 00026 WvMagicCircle::~WvMagicCircle() 00027 { 00028 // nothing special 00029 } 00030 00031 00032 size_t WvMagicCircle::used() 00033 { 00034 int x = tail - head; 00035 if (x < 0) 00036 x += size; 00037 assert(x >= 0); 00038 assert(x < size); 00039 00040 return x; 00041 } 00042 00043 00044 size_t WvMagicCircle::put(const void *data, size_t len) 00045 { 00046 size_t max = left(); 00047 size_t chunk1; 00048 00049 if (len > max) 00050 len = max; 00051 00052 chunk1 = size - tail; 00053 if (len < chunk1) 00054 chunk1 = len; 00055 00056 #if 0 00057 WvLog log("put", WvLog::Info); 00058 log("put: head %s, tail %s, size %s, len %s, chunk1 %s\n", 00059 head, tail, size, len, chunk1); 00060 #endif 00061 00062 memcpy(circle + tail, data, chunk1); 00063 if (chunk1 < len) 00064 memcpy(circle, (char *)data + chunk1, len - chunk1); 00065 00066 tail = (tail + len) % size; 00067 00068 return len; 00069 } 00070 00071 00072 size_t WvMagicCircle::get(void *data, size_t len) 00073 { 00074 size_t max = used(); 00075 size_t chunk1; 00076 00077 if (len > max) 00078 len = max; 00079 00080 chunk1 = size - head; 00081 if (chunk1 > len) 00082 chunk1 = len; 00083 00084 memcpy(data, circle + head, chunk1); 00085 if (chunk1 < len) 00086 memcpy((char *)data + chunk1, circle, len - chunk1); 00087 00088 head = (head + len) % size; 00089 00090 return len; 00091 } 00092 00093 00094 size_t WvMagicCircle::skip(size_t len) 00095 { 00096 size_t max = used(); 00097 00098 if (len > max) 00099 len = max; 00100 00101 head = (head + len) % size; 00102 00103 return len; 00104 }