循环数组部分的返回地址



所以我有一个最大大小为2097152的圆形数组,我希望它填充到524288,并返回保存524288个索引的地址。然后填充另一个524288,做同样的操作。一直这样做,因为它是一个圆形数组。

我正在通过TCP获得数据流。这些数据有不同的大小,但现在我只想用数字填充我的数组。
我不知道该怎么处理。到目前为止我有这个:

    #include <sys/socket.h>
    #include <sys/types.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <errno.h>
    #include <arpa/inet.h>
    #include <stdbool.h>


    typedef struct circular_buffer
    {
        void *buffer;     // data buffer
        void *buffer_end; // end of data buffer
        size_t capacity;  // maximum number of items in the buffer
        size_t count;     // number of items in the buffer
        size_t sz;        // size of each item in the buffer
        void *head;       // pointer to head
        void *tail;       // pointer to tail
    } circular_buffer;
    void cb_init(circular_buffer *cb, size_t capacity, size_t sz)
    {
        cb->buffer = malloc(capacity * sz);
        if(cb->buffer == NULL)
            {
            printf("myError: Buffer returned Null");
            }
        cb->buffer_end = (char *)cb->buffer + capacity * sz;
        cb->capacity = capacity;
        cb->count = 0;
        cb->sz = sz;
        cb->head = cb->buffer;
        cb->tail = cb->buffer;
    }
    void cb_free(circular_buffer *cb)
    {
        free(cb->buffer);
        // clear out other fields too, just to be safe
    }
    void cb_push_back(circular_buffer *cb, const void *item)
    {
        if(cb->count == cb->capacity)
            // handle error
        memcpy(cb->head, item, cb->sz);
        cb->head = (char*)cb->head + cb->sz;
        if(cb->head == cb->buffer_end)
            cb->head = cb->buffer;
        cb->count++;
    }

int main()
{
 int *arr = malloc (BUFFER_LEN * sizeof *arr);
int i;
for(i = 0; i <= BUFFER_LEN; i++) { arr[i] = i; }
   return(0);
}

您可以使用地址运算符(&)返回数据的开头,并像访问数组一样访问它。例如

char *fill_cb(circular_buffer *cb, char *buf, size_t sz)
{
    /* Assume there is room in the buffer: caller must check before calling this function */
    if(cb->tail + sz < cb->buffer_end) {
        memcpy(cb->tail, buf, sz);
        cb->tail += sz;
        cb->count += sz;
        return cb->tail - sz;
    } else {
        size_t tail_room = cb->buffer_end - cb->tail;
        memcpy(cb->tail, buf, tail_room);
        memcpy(cb->buffer, buf + tail_room, sz - tail_room);
        cb->tail = cb->buffer + sz - tail_room;
        return cb->buffer_end - tail_room;
    }
}

现在你可以使用这个指针访问循环缓冲区中的内存,就像访问数组一样

my_data = fill_cb(cb, buf, 20);
do_stuff(my_data[10]);

然而,这只会在你没有换行的时候起作用!数组访问要求内存是连续的。但是我们在循环缓冲区中进行了封装。因此,对于using程序来说,返回一个指向插入数据起始位置的指针是没有用的。您需要编写访问方法以从循环缓冲区中获取数据。在c++中,你可以重载[]使它看起来像一个数组。在C语言中,你需要为它们编写函数。

基本上,你希望有一个像你的图表一样包装的内存区域,但内存是平坦的,如果你返回数据的开始的地址,并从那里连续访问,那么你将阅读过去的循环缓冲区的结束(并在未定义的行为)。

我以前做过一些这样的循环缓冲区/环队列。下面是我用过的一个版本。源代码是完整的,并有一个演示/诊断程序。它应该是可构建和可运行的,而不需要[much:-)]更改。

这个的核心,体现在.h文件中,已经在我的代码库中浮动了10-20年,所以它有一些经验。因此,我根据我的实际使用和经验添加了一些东西。

和你的版本有一些不同。不一定是更好或更坏——只是不同。希望这将给你一些关于你自己的代码的想法。

对于一个,只有一个指向队列开始的指针。enqueue元素[您命名为cb_head]是一个索引,而不是指针。dequeue [cb_tail]也是如此。从我的经验来看,这使得代码更简单,在速度方面达到了标准[有时甚至更快]。

虽然我有使用指针指向所有东西的版本,但它们有指向特定的 [struct]类型的指针,而不是指向void *指针和"sizeof"元素。但是,要在C中做到这一点,需要大量的CPP宏[或元编程]技巧,以获得c++模板的效果。

使用索引和指针的另一个原因是创建多线程/线程安全队列。这并没有被设计到这个特定的版本中,但是qrngnew_lck有一个粗略的例子,它会使用锁(例如pthread_mutex_lock/pthread_mutex_unlock)。

此外,作为互斥锁的替代方案,可以使用stdatomic.h(例如atomic_compare_exchange*)中的原语来更改队列/队列解列值。如果这些值是intvoid *

,那么使用它会容易得多。

当处理大量数据(例如来自recv)时,最有用的是知道在单个块(即memcpy)中可以复制多少单元格,而不是单独进行推送和弹出[这是缓慢的]。

同样,维护队列中元素数量的单独计数也没有必要,因为这很容易从enqueue和dequeue的值中计算出来。

感兴趣的事情是:

  1. 可用于排队数据的空闲单元总数
  2. 单个memcpy
  3. 可用的连续空闲单元数
  4. 待退出队列的已填充单元格总数
  5. 可以用单个memcpy提取的待定的连续填充单元格数

无论如何,代码如下。三个文件:qrng.hqrng.cqrngdemo.c

抱歉关于qrng*。这是个人的签名风格(也就是"怪癖")。它可以很容易地在任何地方都是ring[但是,因为我有几个不同的版本,我使用这个命名来避免在C的命名空间中发生冲突]。它也可能是[说]cb无处不在:-)


qrng.h:

// ovrlib/qrng.h -- ring queue control
#ifndef _ovrlib_qrng_h_
#define _ovrlib_qrng_h_
#define QRNGMAGIC       0xDEAFDEAD
#define QRNGINLINE      static inline
#define _QRNGOFF(_itm) 
    ((long) _itm)
#define QRNGOFF(_qrng,_itm) 
    _QRNGOFF(_qrng->_itm)
#define QRNG_FMT 
    "deq=%ld enq=%ld pend=%ld/%ld avail=%ld/%ld qmax=%ld"
#define QRNG_PRT(_qrng) 
    QRNGOFF(_qrng,qrng_deq), 
    QRNGOFF(_qrng,qrng_enq), 
    _QRNGOFF(qrng_pend_buf(_qrng)), 
    _QRNGOFF(qrng_pend_tot(_qrng)), 
    _QRNGOFF(qrng_avail_buf(_qrng)), 
    _QRNGOFF(qrng_avail_tot(_qrng)), 
    QRNGOFF(_qrng,qrng_qmax)
// pointer to queue data item
// NOTES:
// (1) _always_ use void *
// (2) the way this is used, setting this to _anything_ else will _not_ work
typedef void *queitm_p;
typedef const void *queitm_pc;
// queue index
// NOTES:
// (1) _must_ be signed
// (2) for most queues, an int is sufficient
#ifdef QRNG_BIGIDX
typedef long qidx_t;
#else
typedef int qidx_t;
#endif
typedef long qlen_t;
typedef unsigned int u32;
typedef struct quering_struct quering_t;
typedef quering_t *quering_p;
typedef const quering_t *quering_pc;
struct quering_struct {
    u32 qrng_magic;                     // magic number
    u32 qrng_stat;                      // status
    int qrng_algn[2];                   // align to 64 byte boundary
    // WARNING:
    // (1) accesses to these via sysxchgl require them in
    //     _exactly_ this order -- do _not_ reorder these
    // (2) for 64b mode (cmpxchg16b), these must be aligned to a 16 byte
    //     boundary
    qidx_t qrng_deq;                    // dequeue pointer
    qidx_t qrng_enq;                    // enqueue pointer
    qidx_t qrng_siz;                    // size of queitm_t
    queitm_p qrng_base;                 // base address of ring buffer
    qidx_t qrng_qmax;                   // number of queue elements
};
// equates to status
#define QRNGALLOC       (1u << 0)       // 1=qrng_base is allocated on heap
// qrng_len -- get byte offset/length from index/count
QRNGINLINE qlen_t
qrng_len(quering_p qrng,qidx_t idx)
{
    qlen_t len;
    len = idx;
    len *= qrng->qrng_siz;
    return len;
}
// qrng_ptr -- get flat pointer to queue element
QRNGINLINE queitm_p
qrng_ptr(quering_p qrng,qidx_t idx)
{
    queitm_p ptr;
    ptr = qrng->qrng_base;
    ptr += qrng_len(qrng,idx);
    return ptr;
}
// qrng_wrap_dec -- wrap queue index after decrement
QRNGINLINE qidx_t
qrng_wrap_dec(quering_p qrng,qidx_t qitm,qidx_t inc)
{
    qitm -= inc;
    if (qitm < 0)
        qitm += qrng->qrng_qmax;
    return qitm;
}
// qrng_wrap_inc -- wrap queue index after increment
QRNGINLINE qidx_t
qrng_wrap_inc(quering_p qrng,qidx_t qitm,qidx_t inc)
{
    qidx_t dif;
    qitm += inc;
    dif = qitm - qrng->qrng_qmax;
    if (dif >= 0)
        qitm = dif;
    return qitm;
}
// qrng_reset -- reset queue pointers
QRNGINLINE void
qrng_reset(quering_p qrng)
{
    qrng->qrng_enq = 0;
    qrng->qrng_deq = 0;
}
// qrng_full -- decide if qrng queue is full
// RETURNS: 1=full
QRNGINLINE int
qrng_full(quering_p qrng)
{
    qidx_t qenq;
    qenq = qrng_wrap_inc(qrng,qrng->qrng_enq,1);
    return (qenq == qrng->qrng_deq);
}
// _qrng_empty -- decide if qrng queue is empty
// RETURNS: 1=empty
QRNGINLINE int
_qrng_empty(quering_p qrng,qidx_t enq)
{
    return (qrng->qrng_deq == enq);
}
// qrng_empty -- decide if qrng queue is empty
// RETURNS: 1=empty
QRNGINLINE int
qrng_empty(quering_p qrng)
{
    return _qrng_empty(qrng,qrng->qrng_enq);
}
// qrng_avail_buf -- amount that can be added by single memcpy
QRNGINLINE qidx_t
qrng_avail_buf(quering_p qrng)
{
    qidx_t len;
    len = qrng->qrng_deq - qrng->qrng_enq;
    if (len <= 0) {
        len = qrng->qrng_qmax - qrng->qrng_enq;
        if (qrng->qrng_deq == 0)
            --len;
    }
    else
        --len;
    return len;
}
// qrng_avail_tot_ptr -- total amount that can be added
QRNGINLINE qidx_t
qrng_avail_tot_ptr(quering_p qrng,qidx_t deq,qidx_t enq)
{
    qidx_t len;
    len = deq - enq;
    if (len <= 0)
        len += qrng->qrng_qmax;
    --len;
    return len;
}
// qrng_avail_tot -- total amount that can be added
QRNGINLINE qidx_t
qrng_avail_tot(quering_p qrng)
{
    return qrng_avail_tot_ptr(qrng,qrng->qrng_deq,qrng->qrng_enq);
}
// qrng_pend_buf -- amount that may be dequeued by single memcpy
QRNGINLINE qidx_t
qrng_pend_buf(quering_p qrng)
{
    qidx_t len;
    len = qrng->qrng_enq - qrng->qrng_deq;
    if (len < 0)
        len = qrng->qrng_qmax - qrng->qrng_deq;
    return len;
}
// qrng_pend_tot -- total amount that may be dequeued
QRNGINLINE qidx_t
qrng_pend_tot(quering_p qrng)
{
    qidx_t len;
    len = qrng->qrng_enq - qrng->qrng_deq;
    if (len < 0)
        len += qrng->qrng_qmax;
    return len;
}
// qrng_deq_buf -- dequeue buffer from qrng queue
QRNGINLINE void
qrng_deq_buf(quering_p qrng,qidx_t inclen)
// inclen -- amount to increment
{
    qrng->qrng_deq = qrng_wrap_inc(qrng,qrng->qrng_deq,inclen);
}
// qrng_enq_buf -- enqueue buffer into qrng queue
QRNGINLINE void
qrng_enq_buf(quering_p qrng,qidx_t inclen)
// inclen -- amount to increment
{
    qrng->qrng_enq = qrng_wrap_inc(qrng,qrng->qrng_enq,inclen);
}
// /home/cae/OBJ/ovrgen/ovrlib/qrng.proto -- prototypes
// FILE: /home/cae/preserve/ovrstk/ovrlib/qrng.c
// ovrlib/qrng -- ring queue common control
    // _qrngnoalloc -- handle alloc failure
    void
    _qrngnoalloc(quering_p qrng,int sverr);
    // qrng_setup -- passive setup
    // RETURNS: 1=initialized
    int
    qrng_setup(quering_p qrng,queitm_p bp,qidx_t siz,qidx_t cnt);
    // qrng_alloc -- allocate ring queue
    queitm_p
    qrng_alloc(quering_p qrng,qidx_t cnt);
    // qrng_free -- free queue
    void
    qrng_free(quering_p qrng);
    // qrng_deq_sgl -- dequeue single element from qrng queue
    queitm_p
    qrng_deq_sgl(quering_p qrng);
    // qrng_enq_sgl -- enqueue single element into qrng queue
    queitm_p
    qrng_enq_sgl(quering_p qrng,queitm_p qitm);
    // qrngnew_lck -- enqueue multiple items into qrng queue (syslock)
    // RETURNS: pointer to items to store (or NULL)
    queitm_p
    qrngnew_lck(quering_p qrng,qidx_t cnt,quering_p rlsdeq);
    // _qrngnew_init -- do special type-specific initialization
    void
    _qrngnew_init(queitm_p qitm);
    // _qrngnew_onfull -- decide if capture is stopped because queue is full
    queitm_p
    _qrngnew_onfull(quering_p qrng,qidx_t rtn);
    // qrngcowbrk -- break copy-on-write
    void
    qrngcowbrk(quering_p qrng);
    // qrngfault -- output fault
    void
    qrngfault(quering_p qrng,const char *fmt,...) __attribute__((__format__(__printf__,2,3)));
#endif

qrng.c:

// ovrlib/qrng -- ring queue common control
#include <qrng.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#if 0
#define zprt(_lvl,_fmt...)      fprintf(stderr,_fmt)
#else
#define zprt(_lvl,_fmt...)      /**/
#endif
// _qrngnoalloc -- handle alloc failure
void
_qrngnoalloc(quering_p qrng,int sverr)
{
    qrngfault(qrng,"_qrngnoalloc: unable to allocate buffer -- %sn",
        strerror(sverr));
}
// qrng_setup -- passive setup
// RETURNS: 1=initialized
int
qrng_setup(quering_p qrng,queitm_p bp,qidx_t siz,qidx_t cnt)
{
    int initflg;
#ifdef CPLXCVTLNG
    if ((CPLXCVTLNG(qrng) % 16) != 0)
        qrngfault("qrngsetup: alignment fault -- qrng=%pn",qrng);
#endif
    do {
        initflg = (qrng->qrng_magic != QRNGMAGIC);
        if (initflg)
            memset(qrng,0,sizeof(quering_t));
        qrng->qrng_magic = QRNGMAGIC;
        qrng->qrng_siz = siz;
        // allocate space for queue
        if (bp == NULL)
            bp = qrng_alloc(qrng,cnt);
        else
            qrng_free(qrng);
        qrng->qrng_base = bp;
        qrng->qrng_qmax = cnt;
        // break copy-on-write
        qrngcowbrk(qrng);
    } while (0);
    qrng_reset(qrng);
    return initflg;
}
// qrng_alloc -- allocate ring queue
queitm_p
qrng_alloc(quering_p qrng,qidx_t cnt)
{
    queitm_p qitm;
    int sverr;
    do {
        qitm = qrng->qrng_base;
        // don't realloc if old and new sizes match -- just reset the pointers
        if (qitm != NULL) {
            if (cnt == qrng->qrng_qmax) {
                break;
            }
        }
        // free the old queue
        qrng_free(qrng);
        // allocate the queue
        qitm = calloc(cnt,qrng->qrng_siz);
        sverr = errno;
        // fault on alloc failure
        if (qitm == NULL)
            _qrngnoalloc(qrng,sverr);
        qrng->qrng_stat |= QRNGALLOC;
    } while (0);
    qrng_reset(qrng);
    return qitm;
}
// qrng_free -- free queue
void
qrng_free(quering_p qrng)
{
    queitm_p qitm;
    do {
        qitm = qrng->qrng_base;
        if (qitm == NULL) {
            break;
        }
        if (qrng->qrng_stat & QRNGALLOC) {
            free(qitm);
        }
    } while (0);
    qrng->qrng_base = NULL;
    qrng->qrng_stat &= ~QRNGALLOC;
}
// qrng_deq_sgl -- dequeue single element from qrng queue
queitm_p
qrng_deq_sgl(quering_p qrng)
{
    qidx_t deq;
    queitm_p qrtn;
    do {
        if (qrng_empty(qrng)) {
            qrtn = NULL;
            break;
        }
        deq = qrng->qrng_deq;
        qrtn = qrng_ptr(qrng,deq);
        qrng->qrng_deq = qrng_wrap_inc(qrng,deq,1);
    } while (0);
    return qrtn;
}
// qrng_enq_sgl -- enqueue single element into qrng queue
queitm_p
qrng_enq_sgl(quering_p qrng,queitm_p qitm)
// qitm -- item to enqueue (if NULL, caller will do copy on return)
{
    qidx_t enq;
    queitm_p qrtn;
    do {
        if (qrng_full(qrng)) {
            qrtn = NULL;
            break;
        }
        enq = qrng->qrng_enq;
        qrtn = qrng_ptr(qrng,enq);
        // we give the caller the option of doing the copy manually or letting
        // us do it
        if (qitm != NULL)
            memcpy(qrtn,qitm,qrng->qrng_siz);
        qrng->qrng_enq = qrng_wrap_inc(qrng,enq,1);
    } while (0);
    return qrtn;
}
// qrngnew_lck -- enqueue multiple items into qrng queue (syslock)
// RETURNS: pointer to items to store (or NULL)
queitm_p
qrngnew_lck(quering_p qrng,qidx_t cnt,quering_p rlsdeq)
{
    qidx_t nenq;
    qidx_t ndeq;
    qidx_t odeq;
    qidx_t oenq;
    int stopflg;
    int wflg;
    int dflg;
    int ovflg;
    queitm_p optr;
    stopflg = 0;
    // lock it
    //SYSLOCKQ(&qrng->qrng_lock,0);
    do {
        // grab the old values
        odeq = qrng->qrng_deq;
        oenq = qrng->qrng_enq;
        do {
            // point to one beyond where we wish to store
            nenq = qrng_wrap_inc(qrng,oenq,cnt);
            // decide if we wrapped the enqueue pointer
            wflg = (nenq < oenq);
            // decide if dequeue increment is positive (non-negative)
            dflg = (nenq >= odeq);
            // decide on overflow
            // NOTE: there is an elaborate explanation for the overflow
            // logic in qrng.m5m
            if (oenq >= odeq)
                ovflg = wflg && dflg;
            else
                ovflg = (wflg != dflg);
            // [initial] filling of queue:
            // (1) enq was higher than deq and it did _not_ wrap
            // (2) enq was lower than deq and it did _not_ touch/go over
            if (! ovflg) {
                ndeq = odeq;
                break;
            }
            // advance the dequeue pointer to make room
            ndeq = qrng_wrap_inc(qrng,nenq,1);
        } while (0);
        // allow caller to "release" the dequeued nodes
        if (rlsdeq != NULL) {
            rlsdeq->qrng_deq = odeq;
            rlsdeq->qrng_enq = ndeq;
        }
        // lay down the new pointers
        qrng->qrng_enq = nenq;
        qrng->qrng_deq = ndeq;
    } while (0);
    // zap the type (ASAP)
    // NOTE: there is a slight (virtually non-existent) race condition here
    // which only occurs if we get held off too long and a dump begins
    do {
        if (stopflg) {
            optr = _qrngnew_onfull(qrng,oenq);
            break;
        }
        optr = qrng_ptr(qrng,oenq);
        _qrngnew_init(optr);
    } while (0);
    // unlock it
    //SYSUNLOCKQ(&qrng->qrng_lock);
    return optr;
}
// _qrngnew_init -- do special type-specific initialization
void
_qrngnew_init(queitm_p qitm)
{
    //ARGV_USED(qitm);
}
// _qrngnew_onfull -- decide if capture is stopped because queue is full
queitm_p
_qrngnew_onfull(quering_p qrng,qidx_t rtn)
{
    queitm_p ptr;
    qrngfault(qrng,"qrngnew: stop on fulln");
    ptr = NULL;
    return ptr;
}
// qrngcowbrk -- break copy-on-write
void
qrngcowbrk(quering_p qrng)
{
    qlen_t len;
    len = qrng_len(qrng,qrng->qrng_qmax);
    if (len > 0)
        memset(qrng->qrng_base,0,len);
}
// qrngfault -- output fault
void
qrngfault(quering_p qrng,const char *fmt,...)
{
    va_list ap;
    va_start(ap,fmt);
    vfprintf(stderr,fmt,ap);
    va_end(ap);
    exit(1);
}

qrngdemo.c:

// qrngdemo/qrngdemo -- test/demo program for qrng
#include <qrng.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int opt_v;
qidx_t opt_M;
int opt_T;
#define dbgprt(_fmt...) 
    do { 
        if (opt_v) 
            printf(_fmt); 
    } while (0)
#define fault(_fmt...) 
    do { 
        printf(_fmt); 
        exit(1); 
    } while (0)
quering_t sampque;
#ifndef MAXCNT
#if 0
#define MAXCNT      524288
#else
#define MAXCNT      337
#endif
#endif
typedef struct {
    unsigned int samp_pos;
    unsigned int samp_neg;
} sample_t;
typedef sample_t *sample_p;
unsigned int filloff;
unsigned int cmpoff;
sample_p temp;
// sampsetup -- do setup of sample queue
void
sampsetup(quering_p sampq)
{
    if (opt_M < 3)
        opt_M = 3;
    qrng_setup(sampq,NULL,sizeof(sample_t),opt_M);
    temp = calloc(opt_M + 10,sizeof(sample_t));
}
// randval -- get random count
qidx_t
randval(qidx_t max)
{
    qidx_t cnt;
    cnt = rand() % opt_M;
    if (cnt <= 0)
        cnt = 1;
    if (cnt > max)
        cnt = max;
    return cnt;
}
// fill -- fill queue
void
fill(quering_p sampq)
{
    sample_p samp;
    qidx_t addcnt;
    qidx_t maxcnt;
    qidx_t xcnt;
    qidx_t idx;
    maxcnt = qrng_avail_tot(sampq);
    addcnt = randval(maxcnt);
    dbgprt("fill: ENTER maxcnt=%ld addcnt=%ldn",
        _QRNGOFF(maxcnt),_QRNGOFF(addcnt));
    // fill linear buffer
    for (idx = 0;  idx < addcnt;  ++idx) {
        samp = &temp[idx];
        samp->samp_pos = filloff;
        samp->samp_neg = ~filloff;
        filloff += 1;
    }
    dbgprt("fill: TEMP %8.8X/%8.8Xn",
        temp[0].samp_pos,temp[addcnt - 1].samp_pos);
    // copy linear buffer into ring queue
    for (idx = 0;  addcnt > 0;  idx += xcnt, addcnt -= xcnt) {
        xcnt = qrng_avail_buf(sampq);
        if (xcnt > addcnt)
            xcnt = addcnt;
        if (xcnt <= 0)
            break;
        dbgprt("fill: COPY %8.8X/%8.8X -- xcnt=%ld " QRNG_FMT "n",
            temp[idx].samp_pos,temp[idx + xcnt - 1].samp_pos,
            _QRNGOFF(xcnt),
            QRNG_PRT(sampq));
        memcpy(qrng_ptr(sampq,sampq->qrng_enq),&temp[idx],qrng_len(sampq,xcnt));
        qrng_enq_buf(sampq,xcnt);
    }
    dbgprt("fill: EXIT " QRNG_FMT "n",QRNG_PRT(sampq));
}
// cmp -- compare queue
void
cmp(quering_p sampq)
{
    sample_p samp;
    qidx_t cmpcnt;
    qidx_t maxcnt;
    qidx_t xcnt;
    qidx_t chkcnt;
    qidx_t idx;
    maxcnt = qrng_pend_tot(sampq);
    cmpcnt = randval(maxcnt);
    dbgprt("cmp: ENTER maxcnt=%ld cmpcnt=%ldn",
        _QRNGOFF(maxcnt),_QRNGOFF(cmpcnt));
    // copy data from ring queue into linear buffer
    chkcnt = 0;
    for (idx = 0;  cmpcnt > 0;  idx += xcnt, cmpcnt -= xcnt) {
        xcnt = qrng_pend_buf(sampq);
        if (xcnt > cmpcnt)
            xcnt = cmpcnt;
        if (xcnt <= 0)
            break;
        chkcnt += xcnt;
        memcpy(&temp[idx],qrng_ptr(sampq,sampq->qrng_deq),qrng_len(sampq,xcnt));
        dbgprt("cmp: COPY %8.8X/%8.8X -- xcnt=%ld " QRNG_FMT "n",
            temp[idx].samp_pos,temp[idx + xcnt - 1].samp_pos,
            _QRNGOFF(xcnt),
            QRNG_PRT(sampq));
        qrng_deq_buf(sampq,xcnt);
    }
    if (chkcnt > 0)
        dbgprt("cmp: TEMP %8.8X/%8.8X chkcnt=%ldn",
            temp[0].samp_pos,temp[chkcnt - 1].samp_pos,_QRNGOFF(chkcnt));
    // check linear buffer
    for (idx = 0;  idx < chkcnt;  ++idx) {
        samp = &temp[idx];
        if ((samp->samp_pos != cmpoff) || (samp->samp_neg != ~cmpoff))
            fault("cmp: failure -- idx=%d samp_pos=%8.8X cmpoff=%8.8Xn",
                idx,samp->samp_pos,cmpoff);
        cmpoff += 1;
    }
    dbgprt("cmp: EXIT " QRNG_FMT "n",QRNG_PRT(sampq));
}
// main -- main program
int
main(int argc,char **argv)
{
    char *cp;
    --argc;
    ++argv;
    opt_M = MAXCNT;
    opt_T = 10000000;
    for (;  argc > 0;  --argc, ++argv) {
        cp = *argv;
        if (*cp != '-')
            break;
        switch (cp[1]) {
        case 'M':
            opt_M = strtol(cp,&cp,10);
            break;
        case 'T':
            opt_T = strtol(cp,&cp,10);
            break;
        case 'v':
            opt_v = 1;
            break;
        }
    }
    sampsetup(&sampque);
    for (int iter = opt_T;  iter >= 0;  --iter) {
        fill(&sampque);
        cmp(&sampque);
    }
    qrng_free(&sampque);
    return 0;
}

相关内容

  • 没有找到相关文章

最新更新