Esempio n. 1
0
File: hashmap.cpp Progetto: kayw/mnb
void HashMap<Key, T, Hasher, EqualKey, Alloc>::
  refillBucket(){
     NodePointer pprev = static_cast<NodePointer>(&bucket_start_node_); 
     NodePointer pcurr = pprev->next_;
     if (pcurr != nullptr) {
         size_type curr_index = bucketIndex(pcurr->hash_);
         bucket_list_[curr_index] = pcurr;
         //size_type prev_index = curr_index;
         for (pprev = pcurr, pcurr = pcurr->next_; pcurr != nullptr; pcurr = pprev->next_) {
             curr_index = bucketIndex(pcurr->hash_);
             //if (curr_index == prev_index) {
             //    pprev = pcurr;
             //    continue;
             //}
             if (bucket_list_[curr_index] == nullptr) {
                 bucket_list_[curr_index] = pprev;
                 pprev = pcurr;
                 //prev_index = curr_index;
             }
             else{
                 NodePointer pp = pcurr;
                 NodePointer np = pcurr->next_;
                 Key curkey = pcurr->value_.first;
                 Key nkey = np->value_.first;
                 for(; np != nullptr && key_equal()(curkey, nkey);
                   np = np->next_,nkey = np->value_.first,pp = pp->next_)
                   ;
                 pprev->next_ = np;
                 pp->next_ = bucket_list_[curr_index]->next_;
                 bucket_list_[curr_index]->next_ = pcurr;
            }
        }
     }
  }
Esempio n. 2
0
File: hashmap.cpp Progetto: kayw/mnb
iterator HashMap<Key, T, Hasher, EqualKey, Alloc>::
  addNode(const ValueType& v){
    NodePointer np = new Node();
    np->hash_ = hash_function()(v.first);
    np->value_ = v;
    if (size_ + 1 > max_load_) {
      rehash(size_+1);
    }
    size_type index = bucketIndex(np->hash_, bucket_count_);
    if (bucket_list_[index] == nullptr) {
      NodePointer pStart = static_cast<NodePointer>(&bucket_start_node_);
      np->next_ = pStart->next_;
      pStart->next_ = np;
      bucket_list_[index] = pStart;
      if (np->next_ != nullptr) {
        bucket_list_[bucketIndex(np->next_->hash_, bucket_count_)]
          = np->next_;
      }
    }
    else{
      np->next_ = bucket_list_[index]->next_;
      bucket_list_[index]->next_ = np;
    }
    ++size_;
    return iterator(np);
  }
// Timer IDs are implemented using a free-list;
// there's a vector initialized with:
//    X[i] = i + 1
// and nextFreeTimerId starts with 1.
//
// Allocating a timer ID involves taking the ID from
//    X[nextFreeTimerId]
// updating nextFreeTimerId to this value and returning the old value
//
// When the timer ID is allocated, its cell in the vector is unused (it's a
// free list). As an added protection, we use the cell to store an invalid
// (negative) value that we can later check for integrity.
//
// (continues below).
int QAbstractEventDispatcherPrivate::allocateTimerId()
{
    int timerId, newTimerId;
    int at, *b;
    do {
        timerId = nextFreeTimerId; //.loadAcquire(); // ### FIXME Proper memory ordering semantics

        // which bucket are we looking in?
        int which = timerId & TimerIdMask;
        int bucket = bucketOffset(which);
        at = bucketIndex(bucket, which);
        b = timerIds[bucket];

        if (!b) {
            // allocate a new bucket
            b = allocateBucket(bucket);
            if (!timerIds[bucket].testAndSetRelease(0, b)) {
                // another thread won the race to allocate the bucket
                delete [] b;
                b = timerIds[bucket];
            }
        }

        newTimerId = prepareNewValueWithSerialNumber(timerId, b[at]);
    } while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId));

    b[at] = -timerId;

    return timerId;
}
int QAbstractEventDispatcherPrivate::allocateTimerId()
{
    int timerId, newTimerId;
    do {
        timerId = nextFreeTimerId;

        // which bucket are we looking in?
        int which = timerId & 0x00ffffff;
        int bucket = bucketOffset(which);
        int at = bucketIndex(bucket, which);
        int *b = timerIds[bucket];

        if (!b) {
            // allocate a new bucket
            b = allocateBucket(bucket);
            if (!timerIds[bucket].testAndSetRelease(0, b)) {
                // another thread won the race to allocate the bucket
                delete [] b;
                b = timerIds[bucket];
            }
        }

        newTimerId = b[at];
    } while (!nextFreeTimerId.testAndSetRelaxed(timerId, newTimerId));

    return timerId;
}
Esempio n. 5
0
File: hashmap.cpp Progetto: kayw/mnb
NodePointer HashMap<Key, T, Hasher, EqualKey, Alloc>::
  findNode(const Key& k) const{
    if (bucket_count_ == 0) {
      return nullptr;
    }
    std::size_t h = hash_function()(k);
    size_type curr_index = bucketIndex(h, bucket_count_);
    NodePointer np = bucket_list_[curr_index];
    while(np != nullptr) {
      np = np->next_;
      if (bucketIndex(np->hash_, bucket_count_) == curr_index
          && key_equal()(np->value_.first, k) ) {
        break;
      }
    }
    return np;
  }
Esempio n. 6
0
int Hash_insert(Hash *self, const void *key, const void *value)
{
	size_t i = bucketIndex(self, key);
	if(!self->buckets[i]){
		self->buckets[i] = newNode(self, key, value);
		return self->buckets[i]? 0:1;
	}
	return bucketInsert(self, i, key, value);
}
Esempio n. 7
0
File: hashmap.cpp Progetto: kayw/mnb
size_type HashMap<Key, T, Hasher, EqualKey, Alloc>::
  bucket_size(size_type n) const{
    NodePointer np = bucket_list_[n];
    size_type rsize = 0;
    while(np != nullptr){
      np = np->next_;
      if (bucketIndex(np->hash_, bucket_count_) )
        ++rsize;
    }
    return rsize;
  }
Esempio n. 8
0
File: hashmap.cpp Progetto: kayw/mnb
void HashMap<Key, T, Hasher, EqualKey, Alloc>::
  removeNode(NodePointer prem){
    size_type index = bucketIndex(prem->hash_, bucket_count_);
    NodePointer pn = bucket_list_[index];
    assert(pn);
    for (; pn->next_ != prem; pn = pn->next_)
      ;
    if (pn == static_cast<NodePointer>(&bucket_start_node_)
        || bucketIndex(pn->hash_, bucket_count_) != index){
      if (prem->next_ == nullptr
          || bucketIndex(prem->next_->hash_, bucket_count_) != index)
        bucket_list_[index] = nullptr;
    }
    if (prem->next_ != nullptr) {
      size_type after_index = bucketIndex(prem->next_->hash_, bucket_count_);
      if (after_index != index)
        bucket_list_[after_index] = pn;
    }
    pn->next_ = prem->next_;
    --size_;
    prem->next_ = nullptr;
    delete prem;
  }
void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
{
    int which = timerId & 0x00ffffff;
    int bucket = bucketOffset(which);
    int at = bucketIndex(bucket, which);
    int *b = timerIds[bucket];

    int freeId, newTimerId;
    do {
        freeId = nextFreeTimerId;
        b[at] = freeId & 0x00ffffff;

        newTimerId = prepareNewValueWithSerialNumber(freeId, timerId);
    } while (!nextFreeTimerId.testAndSetRelease(freeId, newTimerId));
}
// Releasing a timer ID requires putting the current ID back in the vector;
// we do it by setting:
//    X[timerId] = nextFreeTimerId;
// then we update nextFreeTimerId to the timer we've just released
//
// The extra code in allocateTimerId and releaseTimerId are ABA prevention
// and bucket memory. The buckets are simply to make sure we allocate only
// the necessary number of timers. See above.
//
// ABA prevention simply adds a value to 7 of the top 8 bits when resetting
// nextFreeTimerId.
void QAbstractEventDispatcherPrivate::releaseTimerId(int timerId)
{
    int which = timerId & TimerIdMask;
    int bucket = bucketOffset(which);
    int at = bucketIndex(bucket, which);
    int *b = timerIds[bucket];

    Q_ASSERT_X(timerId == -b[at], "QAbstractEventDispatcher::releaseTimerId",
               "Internal error: timer ID not found");

    int freeId, newTimerId;
    do {
        freeId = nextFreeTimerId;//.loadAcquire(); // ### FIXME Proper memory ordering semantics
        b[at] = freeId & TimerIdMask;

        newTimerId = prepareNewValueWithSerialNumber(freeId, timerId);
    } while (!nextFreeTimerId.testAndSetRelease(freeId, newTimerId));
}
Esempio n. 11
0
void Hash_remove(Hash *self, const void *key)
{
	size_t i = bucketIndex(self, key);
	HashNode *node = self->buckets[i];
	if(node){
		if(self->cmp(key, node->key) == 0){
			clearBucket(self, i);
		} else {
			while(node->next){
				if(self->cmp(key, node->next->key) == 0){
					squeezeNext(node);
					self->entryCount--;
					return;
				}
			}
		}
	}
}
Esempio n. 12
0
void half_free( void * pointer_void ) {
	
	U8* pointer = (U8*) pointer_void;
	U8 bucket;
	U8 bucket2;
	U16 v_addr;
	
	// The working block (which will contain all merged blocks in the end)
	block_t block;
	
	// Neighboring block
	block_t block2;
	
	// Go left towards beginning of header block
	pointer -= 4;
	
	// Find if block is in our memory pool
	if ((int)pointer - (int)memory < 0 || (int)pointer - (int)memory >= 32768) {
		
		// We're not doing this
		return;
	}
	
	v_addr = ((int)pointer - (int)memory)/BLOCK_BYTES;
	
	// Get block header info
	getBlockHeader(&block, v_addr);
	
	// If there is a free block to the left:
	if ( (block.v_addr != 0) && !isAllocated(block.prev_mem) ) {
		// Get left block header info
		getBlockHeader(&block2, block.prev_mem);
		
		// Add left block size to working block size
		block.size += block2.size;
		
		// Working block's address takes left block's address
		block.v_addr = block.prev_mem;
		
		// Working block's prev_mem takes left block's prev_mem
		block.prev_mem = block2.prev_mem;
		
		// block.next.prev := block.v_addr	(with _mem)
		setPrevMem(block.next_mem, block.v_addr);
		
		
		// Remove left block from its bucket
		bucket2 = bucketIndex(block2.size);
		if ( block2.v_addr == ramses[bucket2] ){
			clearOccupancy(bucket2);
			
		} else {
			setPrevBuck(block2.next_buck, block2.prev_buck);	// block2.next.prev := block2.prev	(with _buck)
			setNextBuck(block2.prev_buck, block2.next_buck);	// block2.prev.next := block2.next	(with _buck)
			
			// if bucket.head == block2
			if( ramses[bucket2] == block2.v_addr){
				// bucket.head := block2.next				(with _buck)
				ramses[bucket2] = block2.next_buck;
			}
		}
	}
	
	// If there is a free block to the right:
	if ( (block.next_mem != 0) && !isAllocated(block.next_mem) ) {
		
		// Get right block info
		getBlockHeader(&block2, block.next_mem);
		
		// Add right block size to working block size
		block.size += block2.size;
		
		// Set working block's next_mem to right block's next_mem
		block.next_mem = block2.next_mem;
		
		// block.next.prev := block.v_addr			(with _mem)
		setPrevMem(block.next_mem, block.v_addr);
		
		// Remove right block from its bucket
		bucket2 = bucketIndex(block2.size);
		if ( block2.v_addr == ramses[bucket2] ){
			clearOccupancy(bucket2);
			
		} else {
			// block2.next.prev := block2.prev		(with _buck)
			setPrevBuck(block2.next_buck, block2.prev_buck);
			
			// block2.prev.next := block2.next		(with _buck)
			setNextBuck(block2.prev_buck, block2.next_buck);
			
			// if bucket.head == block2
			if( ramses[bucket2] == block2.v_addr){
				// bucket.head := block2.next				(with _buck)
				ramses[bucket2] = block2.next_buck;
			}
		}
	}
	
	// Find bucket for working block
	bucket = bucketIndex(block.size);
	
	// If bucket non-empty, insert working block into bucket by appending to existing head
	// Otherwise, link working block to itself & set as head of bucket
	if (isOccupied(bucket)) {
		// block.next := ramses[bucket].next					(with _buck)
		block.next_buck = getNextBuck(ramses[bucket]);
		
		// block.prev := ramses[bucket].v_addr				(with _buck)
		block.prev_buck = ramses[bucket];
		
		// ramses[bucket].next.prev := block.v_addr		(with _buck)
		setPrevBuck(getNextBuck(ramses[bucket]), block.v_addr);
		
		// ramses[bucket].next := block.v_addr				(with _buck)
		setNextBuck(ramses[bucket], block.v_addr);
	} else {
		// Link working block to itself
		block.next_buck = block.prev_buck = block.v_addr;
		
		// Set working block as head of its bucket
		ramses[bucket] = block.v_addr;
		setOccupancy(bucket);
	}
	
	// Save working block
	memory[block.v_addr*BLOCK_SIZE]			= (block.prev_mem  << 22) | (block.next_mem  << 12) | ((block.size-1) << 2);
	memory[block.v_addr*BLOCK_SIZE + 1]	= (block.prev_buck << 22) | (block.next_buck << 12);
	
	return;
}
Esempio n. 13
0
void* half_alloc( U32 bytes ){
	
	block_t block;
	block_t newblock;
	U8 bucket;
	U8 newbucket;
	U8 i;
	U16 v_addr;
	
	// Request 4 more bytes for the header part
	bytes += 4;
	
	// Find a block in the smallest possible non-empty bucket
	i = bucketIndex( (bytes - 1) >> 5 ) + 1;	// Calculate smallest bucket that could fit
	i += __clz(__rbit(bucketOccupancy >> i));	// Get next non-empty bucket
	
	// Stop if we don't have blocks large enough anymore :(
	if (i > 10) {
		return NULL;
	}
	
	// Store bucket info safely
	bucket = i;
	v_addr = ramses[i];
	
	// Get block header info
	getBlockHeader(&block, v_addr);
	
	// Remove block from bucket linked list
	if (block.v_addr == block.next_buck) {
		// Current block is alone in bucket
		
		clearOccupancy(bucket);
		
	} else {
		// Current block is not alone in bucket
		
		// block.next.prev := block.prev		(with _buck)
		setPrevBuck(block.next_buck, block.prev_buck);
		
		// block.prev.next := block.next		(with _buck)
		setNextBuck(block.prev_buck, block.next_buck);
		
		// Change linked list buckethead (http://www.youtube.com/watch?v=lkeXE6FOf6s)
		ramses[bucket] = block.next_buck;
	}
	
	// Mark block as allocated
	memory[block.v_addr*BLOCK_SIZE] |= 0x0002;
	
	
	if ((block.size*BLOCK_BYTES - bytes >= 32)) {
		// Block needs to be split into 2 blocks
		// (block will be returned, newblock stays in free memory)
	
		// Set new block size (block.size - ceil(bytes/BLOCK_BYTES))
		newblock.size = block.size - ((bytes-1)/BLOCK_BYTES + 1);
		
		// Reduce block size
		block.size -= newblock.size;
		
		// Locate new block
		newblock.v_addr = block.v_addr + block.size;
		
		
		// Put new block into memory linked list
		newblock.prev_mem = block.v_addr		;
		newblock.next_mem = block.next_mem 	;
		
		// block.next.prev := newblock.v_addr			(with _mem)
		setPrevMem(block.next_mem, newblock.v_addr);
		
		block.next_mem 		= newblock.v_addr	;
		
		// Save new next_mem & size to current block
		// (Do not save block.prev_mem! Could overwrite critical data.)
		memory[block.v_addr*BLOCK_SIZE] = memory[block.v_addr*BLOCK_SIZE]
			& ~(LAST10 << 12 | LAST10 << 2)
			| (block.next_mem << 12) | ((block.size-1) << 2);
		
		
		// Find bucket number for new block
		newbucket = bucketIndex(newblock.size);
		
		// If applicable, append new block to existing head of bucket
		if (isOccupied(newbucket)) {
			// newblock.next := ramses[newbucket].next					(with _buck)
			newblock.next_buck = getNextBuck(ramses[newbucket]);
			
			// newblock.prev := ramses[newbucket].v_addr				(with _buck)
			newblock.prev_buck = ramses[newbucket];
			
			// ramses[newbucket].next.prev := newblock.v_addr		(with _buck)
			setPrevBuck(getNextBuck(ramses[newbucket]), newblock.v_addr);
			
			// ramses[newbucket].next := newblock.v_addr				(with _buck)
			setNextBuck(ramses[newbucket], newblock.v_addr);
			
		} else {
			// Link new block to itself
			newblock.next_buck = newblock.prev_buck = newblock.v_addr;
			
			// Set new block as head of its bucket
			ramses[newbucket] = newblock.v_addr;
			setOccupancy(newbucket);
		}
		
		// Save new block & set as unallocated
		memory[newblock.v_addr*BLOCK_SIZE] = (newblock.prev_mem << 22) | (newblock.next_mem << 12) | ((newblock.size-1) << 2);
		memory[newblock.v_addr*BLOCK_SIZE+1] = (newblock.prev_buck << 22) | (newblock.next_buck << 12);
	}
	
	// Return pointer to current block
	return (void*)(memory + block.v_addr*BLOCK_SIZE + 1);
		
}
Esempio n. 14
0
static HashNode *hookBucket(const Hash *self, const void *key)
{
	assume_ptr(self);
	size_t index = bucketIndex(self, key);
	return self->buckets[index];
}
Esempio n. 15
0
File: hashmap.cpp Progetto: kayw/mnb
size_type HashMap<Key, T, Hasher, EqualKey, Alloc>::
  bucket(const Key& k) const{
    std::size_t h = hash_function()(k);
    return bucketIndex(h, bucket_count_);
  }