Пример #1
0
err_t _deque_reallocate_map(const ssize_t item_size, const ssize_t buf_size, deque_t* d, ssize_t nodes_to_add, char add_at_front) {
  const ssize_t old_num_nodes = d->finish.node - d->start.node + 1;
  const ssize_t new_num_nodes = old_num_nodes + nodes_to_add;

  deque_node_t* new_nstart; 

  if( d->map_size > 2 * new_num_nodes ) {
    new_nstart = d->map + (d->map_size - new_num_nodes) / 2 + (add_at_front ? nodes_to_add : 0 );
    if( new_nstart < d->start.node ) {
      // copy from d->start.node to d->finish.node + 1 to new_nstart
      _deque_map_copy_forward(d->start.node, d->finish.node + 1, new_nstart);
    } else {
      // copy backward from d->start.node to d->finish.node + 1 to new_nstart + old_num_nodes elements
      _deque_map_copy_backward(d->start.node, d->finish.node + 1, new_nstart + old_num_nodes);
    }
  } else {
    ssize_t new_map_size = d->map_size + _DEQUE_MAX(d->map_size, nodes_to_add) + 2;
    deque_node_t* new_map = (deque_node_t*) deque_calloc(new_map_size, sizeof(deque_node_t));
    if( ! new_map ) return ENOMEM;

    new_nstart = new_map + (new_map_size - new_num_nodes ) / 2 + (add_at_front ? nodes_to_add : 0 );
    // copy from d->start.node to d->finish.node + 1 to new_nstart 
    _deque_map_copy_forward(d->start.node, d->finish.node + 1, new_nstart);
    deque_free(d->map);

    d->map = new_map;
    d->map_size = new_map_size;
  }
  _deque_set_node(item_size, buf_size, & d->start, new_nstart);
  _deque_set_node(item_size, buf_size, & d->finish, new_nstart + old_num_nodes - 1);
  return 0;
}
Пример #2
0
void test_reallocate(void)
{
  // hit the different reallocate cases.
  // map_size > 2* num_new_nodes
  // add to front, add to back

  {
    // start with copy forward/copy backward.
    deque_node_t nodes[4];

    nodes[0].data = (void*) 0x100;
    nodes[1].data = (void*) 0x101;
    nodes[2].data = (void*) 0x102;
    nodes[3].data = (void*) 0x103;

    // test overlapping copy forward.
    // dstBeg should be before srcBegin
    _deque_map_copy_forward( &nodes[2], &nodes[4], &nodes[1]);
    assert(nodes[0].data == (void*) 0x100);
    assert(nodes[1].data == (void*) 0x102);
    assert(nodes[2].data == (void*) 0x103);
    assert(nodes[3].data == (void*) 0x103);


    nodes[0].data = (void*) 0x100;
    nodes[1].data = (void*) 0x101;
    nodes[2].data = (void*) 0x102;
    nodes[3].data = (void*) 0x103;


    // test overlapping copy backward.
    // dstEnd should be after srcEnd
    _deque_map_copy_backward( &nodes[0], &nodes[2], &nodes[3]);
    assert(nodes[0].data == (void*) 0x100);
    assert(nodes[1].data == (void*) 0x100);
    assert(nodes[2].data == (void*) 0x101);
    assert(nodes[3].data == (void*) 0x103);
  }

  // Now, suppose we've allocated our stuff...
  // let's reallocate.
  {
    deque_t d;
    qioerr err;
    ssize_t saved_size;
    deque_node_t saved_nodes[2*_DEQUE_INITIAL_MAP_SIZE];
    deque_node_t* cur;
    int i;

    // this time, try with map_size < 2*num_new_nodes
    err = deque_init(16, &d, 16*_DEQUE_INITIAL_MAP_SIZE);
    assert(!err);

    // save the pointers.
    assert(d.map_size < 2*_DEQUE_INITIAL_MAP_SIZE);// fits in test buffer
    saved_size = 0;
    for( cur = d.start.node; cur < d.finish.node; ++cur ) {
      saved_nodes[saved_size++].data = cur->data;
    }

    _deque_reallocate_map(16, 512, /* first two args dont matter in this test*/
                          &d, 1, 0 /* not at front */);
    assert(d.map_size > saved_size); // make sure it grew
    i = 0;
    for( cur = d.start.node; cur < d.finish.node && i < saved_size; ++cur ) {
      assert(saved_nodes[i++].data == cur->data);
    } 
    // don't care value of nodes[saved_size], the new slot.

    deque_destroy(&d);

    err = deque_init(16, &d, 16*_DEQUE_INITIAL_MAP_SIZE);
    assert(!err);

    assert(d.map_size < 2*_DEQUE_INITIAL_MAP_SIZE);// fits in test buffer
    saved_size = 0;
    for( cur = d.start.node; cur < d.finish.node; ++cur ) {
      saved_nodes[saved_size++].data = cur->data;
    }

    _deque_reallocate_map(16, 512, /* first two args dont matter in this test*/
                          &d, 1, 1 /* at front */);
    assert(d.map_size > saved_size); // make sure it grew
    // don't care value of nodes[0], the new slot.
    i = 0;
    for( cur = d.start.node; cur < d.finish.node && i < saved_size ; ++cur ) {
      assert(saved_nodes[i++].data == cur->data);
    } 
    // don't care of value of nodes[saved_size+1], the previous new slot.

    deque_destroy(&d);

    // this time, try with map_size > 2*num_new_nodes
    err = deque_init(16, &d, 0);
    assert(!err);

    // save the pointers.
    assert(d.map_size < 2*_DEQUE_INITIAL_MAP_SIZE);// fits in test buffer
    saved_size = 0;
    for( cur = d.start.node; cur < d.finish.node; ++cur ) {
      saved_nodes[saved_size++].data = cur->data;
    }

    _deque_reallocate_map(16, 512, /* first two args dont matter in this test*/
                          &d, 1, 0 /* not at front */);
    i = 0;
    for( cur = d.start.node; cur < d.finish.node; ++cur ) {
      assert(saved_nodes[i++].data == cur->data);
    }
    assert( i == saved_size );

    deque_destroy(&d);

    err = deque_init(16, &d, 0);
    assert(!err);

    // save the pointers.
    assert(d.map_size < 2*_DEQUE_INITIAL_MAP_SIZE);// fits in test buffer
    saved_size = 0;
    for( cur = d.start.node; cur < d.finish.node; ++cur ) {
      saved_nodes[saved_size++].data = cur->data;
    }

    _deque_reallocate_map(16, 512, /* first two args dont matter in this test*/
                          &d, 1, 1 /* at front */);
    i = 0;
    for( cur = d.start.node; cur < d.finish.node; ++cur ) {
      assert(saved_nodes[i++].data == cur->data);
    }
    assert( i == saved_size );

    deque_destroy(&d);
  }
}