2016-08-11 5 views
0

したがって、私は最大サイズ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); 
} 
+2

円形配列とは何ですか?そのようなデータ構造はありません。リングバッファーを意味しますか?あなたのコードをregirする**具体的な**質問がありますか?これはコンサルティングサービスではありません。[ask]を参照してください。 – Olaf

+0

@Olaf私はリングバッファの一部のアドレスを返す方法を尋ねていました。また、リングバッファには異なる名前があり、円形配列、循環バッファとも呼ばれます。 – 2222

+0

あなたの質問は何ですか? – immibis

答えて

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]); 

ただし、これはラップしなかった場合にのみ機能します。配列アクセスは、メモリが連続していると予想します。しかし、私たちは循環バッファーの中を包み込んだ。したがって、挿入されたデータの先頭へのポインタを返すことは、プログラムを使用する上では役に立ちません。循環バッファからデータを取得するためのアクセスメソッドを記述する必要があります。 C++では、[]をオーバーロードして配列のように見せます。 Cでは、これらの関数を記述する必要があります。

基本的には、ダイアグラムのようにラップされたメモリ領域が存在することを期待していますが、メモリはフラットであり、のアドレスを返すと、のデータとアクセスが連続して続きます循環バッファの終わりを過ぎて(未定義の振る舞いに)。

0

これまで、これらの循環バッファ/リングキューのいくつかを行ってきました。以下は私が使ったバージョンの一つです。ソースコードは完成しており、デモ/診断プログラムがあります。ビルド可能で、実行可能でなければなりません。

.hファイルで具体化されているこれの中心的なコアは、コードベースの周りに10〜20年間浮遊しています。このため、実際の使用方法や経験に基づいて追加したものがいくつかあります。

ご使用のバージョンとの違いはいくつかあります。必ずしも良いか悪いのかは違う。うまくいけば、これはあなた自身のコードのためのいくつかのアイデアを与えるでしょう。

キューの先頭へのポインタは1つだけです。エンキュー要素[cb_headという名前のエンキュー要素]は、ポインタではなくインデックスです。デキュー[cb_tail]の場合も同様です。私の経験から、これによりコードが少しシンプルになり、スピードが速くなります。私はすべてへのポインタを使用したバージョンがありますが

は、彼らが特定 [構造体]タイプへのポインタではなく、void *ポインタと「はsizeof」の要素を持っています。しかし、Cでこれを行うには、C++テンプレートの効果を得るために、多くのCPPマクロ[またはメタプログラミング]トリッキーが必要です。

インデックスとポインタを使用する他の理由の1つは、マルチスレッド/スレッドセーフキューを作成することです。これはこの特定のバージョンには設計されていませんが、qrngnew_lckという例ではロックを使用しています。pthread_mutex_lock/pthread_mutex_unlock)。

また、ミューテックスの代替として、stdatomic.h(たとえばatomic_compare_exchange*)のプリミティブを使用して、エンキュー/デキュー値を変更することができます。単一のチャンクにコピーすることができますどのように多くの細胞知ることが最も有効です何、(recvから例えば)大量のデータを扱う場合、これらの値は、int


void *をしている場合は、これを使用する方がはるかに簡単です(すなわち、memcpy)、個々のプッシュやポップ[遅い]を行うのではなく、

また、エンキュー値とデキュー値から簡単に計算できるため、キュー内の要素数の個別カウントを維持する必要はありません。

興味のあるものがあります:データに充填されたセルの単一memcpy

  • 総数ために利用可能な連続した空きセルの
  • 数をキューに利用できる無料の細胞の

    1. 総数は
    2. をデキューする保留します
    3. 単一で抽出することができる連続充填セルの数。memcpy

    とにかく、コードは以下のとおりです。 3つのファイル:qrng.h,qrng.c、およびqrngdemo.cです。

    大変申し訳ございませんがqrng*です。これは個人的な署名スタイル(「quirk」)です。 [ringどこでも簡単にできましたが、いくつかのバージョンがあるので、Cの名前空間での衝突を避けるためにこの名前を使用します。

    // 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 -- %s\n", 
         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=%p\n",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 full\n"); 
    
        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); 
    } 
    

    また


    qrng.h :-)どこでも[言う] cbされている可能性が

    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=%ld\n", 
         _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.8X\n", 
         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=%ld\n", 
         _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=%ld\n", 
          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.8X\n", 
           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; 
    } 
    
  • 関連する問題