int Line::diff_width(void) { int sz = 0; char* diff = str; if(!diff) return 0; while(*diff) { int op = GET_OP(*diff); int cnt = GET_CNT(*diff); diff++; switch(op) { case OP_ADD: case OP_SUB: diff += cnt; case OP_EQ: sz += cnt; break; } } return sz; }
bool AtomicQueue::Dequeue(void* data_item) { const size_t buffer_size = mItemSize * mNumItems; for (;;) { const uint64_t cur_head = mHead; const uint64_t cur_tail = mTail; MemoryBarrier(); // Check if empty (both counter and numbers match) if (cur_head == cur_tail) return false; const uint64_t cur_head_num = GET_NUM(cur_head); memcpy(data_item, static_cast<char*>(mBuffer) + cur_head_num, mItemSize); const uint64_t new_head_num = cur_head_num + mItemSize; const uint64_t head_cnt = GET_CNT(cur_head); // Check if looped through buffer. const uint64_t new_head_val = (new_head_num == buffer_size) ? CONSTRUCT_NEXT_VALUE(head_cnt, 0) : CONSTRUCT_VALUE(head_cnt, new_head_num); if (AtomicCmpSet64(&mHead, cur_head, new_head_val)) break; } return true; }
void AtomicMemPool::Remove(uint32_t index) { uint64_t next_free_index_value = mNextFreeIndex; MemoryBarrier(); const size_t item_size = mItemSize; uint8_t* buffer_ptr = static_cast<uint8_t*>(mBuffer); for (;;) { const uint64_t next_free_index_num = GET_NUM(next_free_index_value); const uint32_t next_free_index = static_cast<uint32_t>(next_free_index_num); uint8_t* remove_loc = &buffer_ptr[item_size*index]; *reinterpret_cast<uint32_t*>(remove_loc) = next_free_index; if (AtomicCmpSet64(&mNextFreeIndex, next_free_index_value, CONSTRUCT_NEXT_VALUE(GET_CNT(next_free_index_value), static_cast<uint64_t>(index)))) { break; } next_free_index_value = mNextFreeIndex; MemoryBarrier(); } }
static int apply(char* diff, char* base, char* dst, int direction) { while(*diff) { int op = GET_OP(*diff); int cnt = GET_CNT(*diff); diff++; if(direction) //reverse { if(op == OP_SUB) op = OP_ADD; else if(op == OP_ADD) op = OP_SUB; } switch(op) { case OP_EQ: while(cnt--) *dst++ = *base++; break; case OP_SUB: while(cnt--) { diff++; base++; } break; case OP_ADD: while(cnt--) *dst++ = *diff++; break; } } *dst = 0; return 0; }
uint32_t AtomicMemPool::Allocate() { uint32_t used_indexes = mUsedIndexes; uint64_t next_free_index_value = mNextFreeIndex; MemoryBarrier(); const size_t item_size = mItemSize; uint8_t* buffer_ptr = static_cast<uint8_t*>(mBuffer); // Check if there are any free items uint32_t next_num = static_cast<uint32_t>(GET_NUM(next_free_index_value)); while (next_num != static_cast<uint32_t>(-1)) { uint8_t* next_free_loc = &buffer_ptr[item_size*next_num]; uint32_t new_next_free_index = *reinterpret_cast<uint32_t*>(next_free_loc); if (AtomicCmpSet64(&mNextFreeIndex, next_free_index_value, CONSTRUCT_NEXT_VALUE(GET_CNT(next_free_index_value), new_next_free_index))) { return next_num; } next_free_index_value = mNextFreeIndex; MemoryBarrier(); next_num = static_cast<uint32_t>(GET_NUM(next_free_index_value)); } // Check if used rest of array const size_t array_size = mNumItems; if (used_indexes < array_size) { uint32_t new_index = AtomicAdd32(&mUsedIndexes, 1); if (new_index < array_size) { return new_index; } } return static_cast<uint32_t>(-1); }
bool AtomicQueue::Enqueue(const void* data_item) { const uint64_t cur_head = mHead; const uint64_t cur_tail = mTail; MemoryBarrier(); const uint64_t cur_head_num = GET_NUM(cur_head); const uint64_t cur_tail_num = GET_NUM(cur_tail); // Check if full (numbers match, but counters do not) if (cur_head_num == cur_tail_num && cur_head != cur_tail) return false; memcpy(static_cast<char*>(mBuffer) + cur_tail_num, data_item, mItemSize); const uint64_t new_tail_num = cur_tail_num + mItemSize; const uint64_t tail_cnt = GET_CNT(cur_tail); // Check if looped through buffer. mTail = (new_tail_num == (mItemSize * mNumItems)) ? CONSTRUCT_NEXT_VALUE(tail_cnt, 0) : CONSTRUCT_VALUE(tail_cnt, new_tail_num); return true; }
static void diff_str(char* s1, char* s2, char* s3) { char* start = s2; char* j; char* last_op = s3; *last_op = 0; for(; *s1; s1++) { int res = 1; for(j = start; *j; j++) { res = (*s1 - *j); if(!res) //Match found break; } if(!res) //Match found { //Fill the gap, if any if(start < j) { last_op = s3; *s3++ = OP_SUB; while(start < j) { if(GET_CNT(*last_op) == MAX_CNT) { last_op = s3; *s3++ = OP_SUB; } *s3++ = *start++; *last_op = *last_op + 1; } } if(GET_OP(*last_op) == OP_EQ) { if(GET_CNT(*last_op) == MAX_CNT) { last_op = s3; *s3++ = OP_EQ; } *last_op = *last_op + 1; } else { last_op = s3; *s3++ = OP_EQ | 0x01; } start++; } else //No match { if(GET_OP(*last_op) == OP_ADD) { if(GET_CNT(*last_op) == MAX_CNT) { last_op = s3; *s3++ = OP_ADD; } *s3++ = *s1; *last_op = *last_op + 1; } else { last_op = s3; *s3++ = OP_ADD | 0x01; *s3++ = *s1; } } } if(*start) { last_op = s3; *s3++ = OP_SUB; while(*start) { if(GET_CNT(*last_op) == MAX_CNT) { last_op = s3; *s3++ = OP_SUB; } *s3++ = *start++; *last_op = *last_op + 1; } } *s3 = 0; }