void HashGrid::AddFlux(const Point &hitPoint, const Vector &wi, const Spectrum &photonFlux) { // Look for eye path hit points near the current hit point Vector hh = (hitPoint - hitPoints->GetBBox().pMin) * invCellSize; const int ix = abs(int(hh.x)); const int iy = abs(int(hh.y)); const int iz = abs(int(hh.z)); std::list<HitPoint *> *hps = grid[Hash(ix, iy, iz)]; if (hps) { std::list<HitPoint *>::iterator iter = hps->begin(); while (iter != hps->end()) { HitPoint *hp = *iter++; const float dist2 = DistanceSquared(hp->position, hitPoint); if ((dist2 > hp->accumPhotonRadius2)) continue; const float dot = Dot(hp->normal, wi); if (dot <= 0.0001f) continue; AtomicInc(&hp->accumPhotonCount); Spectrum flux = photonFlux * hp->material->f(hp->wo, wi, hp->normal) * hp->throughput; AtomicAdd(&hp->accumReflectedFlux.r, flux.r); AtomicAdd(&hp->accumReflectedFlux.g, flux.g); AtomicAdd(&hp->accumReflectedFlux.b, flux.b); } } }
LargeMemoryBlock *ExtMemoryPool::mallocLargeObject(size_t allocationSize) { #if __TBB_MALLOC_LOCACHE_STAT AtomicIncrement(mallocCalls); AtomicAdd(memAllocKB, allocationSize/1024); #endif LargeMemoryBlock* lmb = loc.get(allocationSize); if (!lmb) { BackRefIdx backRefIdx = BackRefIdx::newBackRef(/*largeObj=*/true); if (backRefIdx.isInvalid()) return NULL; // unalignedSize is set in getLargeBlock lmb = backend.getLargeBlock(allocationSize); if (!lmb) { removeBackRef(backRefIdx); loc.rollbackCacheState(allocationSize); return NULL; } lmb->backRefIdx = backRefIdx; STAT_increment(getThreadId(), ThreadCommonCounters, allocNewLargeObj); } else { #if __TBB_MALLOC_LOCACHE_STAT AtomicIncrement(cacheHits); AtomicAdd(memHitKB, allocationSize/1024); #endif } return lmb; }
int RingBuffer::push(const void *p_buf, unsigned int len, const void *p_mem){ unsigned int peek_len = MAGIC_PEEK; rmb(); unsigned int cur_head = m_head; unsigned int cur_tail = m_tail; unsigned char *p_base = (unsigned char*)const_cast<void*>(p_mem); rmb(); if(cur_head - cur_tail + len + sizeof(len) > m_size){ //printf("full cur_head %u len %d cur_tail %u m_size %d \n",cur_head,len,cur_tail,m_size); return -1; //full } rmb(); if(countToIndex(m_head) + len + sizeof(len) > m_size){ //for peek memcpy(p_base+countToIndex(cur_head), &peek_len, sizeof(len)); AtomicAdd(&m_head, m_size - countToIndex(m_head)); return push(p_buf, len, p_mem); }else{ memcpy(p_base+countToIndex(cur_head), &len, sizeof(len)); memcpy(p_base+countToIndex(cur_head)+sizeof(len), p_buf, len); AtomicAdd(&m_head, len+sizeof(len)); if(m_b_real_count) AtomicAdd(&m_real_count, 1); if(m_b_real_size) AtomicAdd(&m_real_size, len+sizeof(len)); return 0; } }
int RingBuffer::remove(const void *p_mem){ unsigned int cur_max_read; unsigned int cur_read; unsigned int len; unsigned char *p_base = (unsigned char*)const_cast<void*>(p_mem); do{ cur_read = m_tail; cur_max_read = m_head; if(cur_read == cur_max_read){ return -1; //empty } len = *(unsigned int*)(p_base + countToIndex(cur_read)); if(len != MAGIC_PEEK){ if(CAS(&m_tail, cur_read, cur_read + len + sizeof(unsigned int))){ if(m_b_real_count) AtomicAdd(&m_real_count, -1); if(m_b_real_size) AtomicAdd(&m_real_size, -(long)(len+sizeof(unsigned int))); return 0; } }else{ if(CAS(&m_tail, cur_read, cur_read + m_size - countToIndex(cur_read))){ return remove(p_mem); } } }while(1); return -1; }
int RingBuffer::pop(void *p_buf, unsigned int *len, const void *p_mem){ unsigned int cur_max_read; unsigned int cur_read; unsigned int in_len = *len; unsigned char *p_base = (unsigned char*)const_cast<void*>(p_mem); do{ rmb(); cur_read = m_tail; cur_max_read = m_head; if(cur_read == cur_max_read){ return -1; //empty } *len = *(unsigned int*)(p_base + countToIndex(cur_read)); if(*len > in_len && *len != MAGIC_PEEK) return -2; //buffer too small if(*len != MAGIC_PEEK){ memcpy(p_buf, p_base + countToIndex(cur_read) + sizeof(unsigned int), *len); if(CAS(&m_tail, cur_read, cur_read + *len + sizeof(unsigned int))){ if(m_b_real_count) AtomicAdd(&m_real_count, -1); if(m_b_real_size) AtomicAdd(&m_real_size, -(long)(*len+sizeof(unsigned int))); return 0; } }else{ //printf("PEEK! \n"); if(CAS(&m_tail, cur_read, cur_read + m_size - countToIndex(cur_read))){ return pop(p_buf, len, p_mem); } } }while(1); return -1; }
/* ============================================================================= * TxFreeThread * ============================================================================= */ void TxFreeThread (Thread* t){ AtomicAdd((volatile intptr_t*)((void*)(&StartTally)), t->Starts); AtomicAdd((volatile intptr_t*)((void*)(&AbortTally)), t->Aborts); // free data structures free(t); }
bool EmuSampler::execute(FlowID fid, uint64_t icount) /* called for every instruction that qemu/gpu executes */ { GI(mode==EmuTiming, icount==1); local_icount+=icount; // There can be several samplers, but each has its own thread //if ( likely(local_icount < 100)) // return !done[fid]; AtomicAdd(&phasenInst, local_icount); AtomicAdd(&totalnInst, local_icount); local_icount = 0; if( likely(totalnInst <= next) ) // This is an likely taken branch, pass the info to gcc return !done[fid]; next += 4*1024*1024; // Note, this is racy code. We can miss a rwdt from time to time, but who cares? if ( done[fid] ) { fprintf(stderr,"X" ); fflush(stderr); { // We can not really, hold the thread, because it can hold locks inside qemu usleep(10000); fprintf(stderr,"X[%d]",fid); } }else{ if (mode==EmuRabbit) fprintf(stderr,"r%d",fid ); else if (mode==EmuWarmup) fprintf(stderr,"w%d",fid ); else if (mode==EmuDetail) fprintf(stderr,"d%d",fid ); else if (mode==EmuTiming) fprintf(stderr,"t%d",fid ); else if (mode==EmuInit) fprintf(stderr,">%d",fid ); else fprintf(stderr,"?%d",fid ); } // An adjustment when adding more than one instruction. Keeps the sample prints valid // Repeat: Note, this is racy code. We can miss a rwdt from time to time, but who cares? if (icount > 1) { while (next < totalnInst) { if (mode==EmuRabbit) fprintf(stderr,"r%d",fid ); next += 4*1024*1024; } next = totalnInst; } return !done[fid]; }
//============================================================================ NetTrans::NetTrans (ENetProtocol protocol, ETransType transType) : m_state(kTransStateWaitServerConnect) , m_result(kNetPending) , m_transId(0) , m_connId(0) , m_protocol(protocol) , m_hasSubTrans(false) , m_timeoutAtMs(0) , m_transType(transType) { AtomicAdd(&s_perf[kPerfCurrTransactions], 1); AtomicAdd(&s_perfTransCount[m_transType], 1); // DebugMsg("%s@%p created", s_transTypes[m_transType], this); }
virtual uval pokeRing(MemTransRef mtr, XHandle otherMT) { ring = id; AtomicAdd(&counter,1); printf("Got message: %s from %lx\n",__func__,(uval)otherMT); Scheduler::Unblock(owner); return 1; }
virtual SysStatus allocRing(MemTransRef mtr, XHandle otherMT) { other = otherMT; AtomicAdd(&counter,1); printf("Got message: from %s\n",__func__, (uval)otherMT); Scheduler::Unblock(owner); return 0; }
//============================================================================ static void DownloadCallback ( ENetError result, void * param, const wchar_t filename[], hsStream * writer ) { if(IS_NET_ERROR(result)) { switch (result) { case kNetErrTimeout: writer->Rewind(); NetCliFileDownloadRequest(filename, writer, DownloadCallback, param); break; default: plString msg = plString::Format("Error getting patcher file: %S", NetErrorToString(result)); plStatusLog::AddLineS("patcher.log", msg.c_str()); if (IS_NET_SUCCESS(s_patchResult)) s_patchResult = result; break; } return; } writer->Close(); delete writer; AtomicAdd(&s_numFiles, -1); if(!s_numFiles) { s_downloadComplete = true; s_updated = true; } }
bool CClient::OnClose() { LOGI("Client Closed!"); delete this; //! 安全的自删除源于底层的彻底的异步分离 AtomicAdd(&g_nTotalCloesed, 1); return true; }
void RWLock::UnlockWrite() { int waitingReaders = AtomicAdd(&fCount, kMaxReaders) + kMaxReaders; if (waitingReaders > 0) fReadSem.Release(waitingReaders); fWriteLock.Unlock(); }
status_t RWLock::LockRead() { status_t error = E_NO_ERROR; if (AtomicAdd(&fCount, 1) < 0) error = fReadSem.Wait(); return error; }
status_t AddressSpace::HandleFault(unsigned int va, bool write, bool user) { va &= ~(PAGE_SIZE - 1); // Round down to a page boundry. fAreaLock.LockRead(); int lastChangeCount = fChangeCount; Area *area = static_cast<Area*>(fAreas.Find(va)); if (area == 0) { fAreaLock.UnlockRead(); return E_BAD_ADDRESS; } PageProtection protection = area->GetProtection(); if ((user && write && !(protection & USER_WRITE)) || (user && !write && !(protection & USER_READ)) || (!user && write && !(protection & SYSTEM_WRITE)) || (!user && !write && !(protection & SYSTEM_READ))) { fAreaLock.UnlockRead(); return E_NOT_ALLOWED; } PageCache *cache = area->GetPageCache(); if (cache == 0) { fAreaLock.UnlockRead(); return E_NOT_ALLOWED; } bool copy = cache->IsCopy(); cache->AcquireRef(); fAreaLock.UnlockRead(); off_t offset = va - area->GetBaseAddress() + area->GetCacheOffset(); Page *page = cache->GetPage(offset, write && cache->IsCopy()); cache->ReleaseRef(); if (page == 0) return E_IO; fAreaLock.LockRead(); if (lastChangeCount != fChangeCount) { // Changes have occured to this address. Make sure that // the area hasn't changed underneath the fault handler. Area *newArea = static_cast<Area*>(fAreas.Find(va)); if (newArea != area || newArea->GetPageCache() != cache || newArea->GetCacheOffset() != offset) fAreaLock.UnlockRead(); return E_BAD_ADDRESS; } // If this is a read from copy-on-write page, it is shared with the // original cache. Mark it read only. if (copy && !write) protection &= ~(USER_WRITE | SYSTEM_WRITE); fPhysicalMap->Map(va, page->GetPhysicalAddress(), protection); fAreaLock.UnlockRead(); AtomicAdd(&fFaultCount, 1); return E_NO_ERROR; }
//============================================================================ static void ManifestCallback ( ENetError result, void * param, const wchar_t group[], const NetCliFileManifestEntry manifest[], unsigned entryCount ) { if(IS_NET_ERROR(result)) { switch (result) { case kNetErrTimeout: NetCliFileManifestRequest(ManifestCallback, nil, s_manifest); break; default: plString msg = plString::Format("Error getting patcher manifest: %S", NetErrorToString(result)); plStatusLog::AddLineS("patcher.log", msg.c_str()); if (IS_NET_SUCCESS(s_patchResult)) s_patchResult = result; break; } return; } #ifndef PLASMA_EXTERNAL_RELEASE if (entryCount == 0) { // dataserver does not contain a patcher s_downloadComplete = true; return; } #endif char ansi[MAX_PATH]; // MD5 check current patcher against value in manifest ASSERT(entryCount == 1); wchar_t curPatcherFile[MAX_PATH]; PathGetProgramName(curPatcherFile, arrsize(curPatcherFile)); StrToAnsi(ansi, curPatcherFile, arrsize(ansi)); if (!MD5Check(ansi, manifest[0].md5)) { // MessageBox(GetTopWindow(nil), "MD5 failed", "Msg", MB_OK); SelfPatcherStream::totalBytes += manifest[0].zipSize; AtomicAdd(&s_numFiles, 1); SetText("Downloading new patcher..."); StrToAnsi(ansi, s_newPatcherFile, arrsize(ansi)); SelfPatcherStream * stream = new SelfPatcherStream; if (!stream->Open(ansi, "wb")) ErrorAssert(__LINE__, __FILE__, "Failed to create file: %s, errno: %u", ansi, errno); NetCliFileDownloadRequest(manifest[0].downloadName, stream, DownloadCallback, nil); } else { s_downloadComplete = true; } }
/// atomic update the destVal static int atomic_update_val(int& destVal, int with, int updateType) { switch (updateType) { case position::POS_OP_ADD: return AtomicAdd(&destVal, with); case position::POS_OP_DEC: return AtomicDec(&destVal, with); case position::POS_OP_ASSIGN: return (destVal = with); default: return destVal; } }
static AX_FORCEINLINE tElement *LinearAlloc( tElement( &arr )[ tSize ], uint32 ¤t, uint32 count, const char *msg = "Allocation failed" ) { AX_ASSERT( count > 0 ); const uint32 base = AtomicAdd( ¤t, count ); if( base + count > tSize ) { AX_ASSERT_MSG( false, msg ); AtomicSub( ¤t, count ); return nullptr; } return &arr[ base ]; }
status_t RWLock::LockWrite() { status_t error = fWriteLock.Lock(); if (error != E_NO_ERROR) return error; int readerCount = AtomicAdd(&fCount, -kMaxReaders); while (readerCount-- > 0) { error = fWriteSem.Wait(); if (error != E_NO_ERROR) break; } return error; }
void FSStats::incStat(StatType type, uval extra_arg /* = 0 */) { switch (type) { case LOOKUP_FAILURE: case LOOKUP_SUCCESS: case CLIENT_CREATED: case CLIENT_CREATED_LAZY_INIT: case CLIENT_CREATED_NON_SHARED: case CLIENT_CREATED_SHARED: case CLIENT_CREATED_FIXED_SHARED: case CLIENT_BECAME_NON_SHARED: case CLIENT_BECAME_SHARED: case CLIENT_SWITCH: case OPEN: case OPEN_RDONLY: case DUP: case REGISTER_CALLBACK: case ACK_USETYPE: case LENGTH_OFFSET: AtomicAdd(&stats[type], 1); break; case OPEN_SIZE: updateSizeArray(openSizes, extra_arg); break; case CLOSE_SIZE: updateSizeArray(closeSizes, extra_arg); break; case MAX_WRITE_SIZE_NON_SHARED: case MAX_WRITE_SIZE_SHARED: statLock.acquire(); if (extra_arg > stats[type]) { second_max_write_shared = stats[type]; stats[type] = extra_arg; nb_max_write_shared = 1; } else if (extra_arg == stats[type]) { nb_max_write_shared++; } statLock.release(); break; default: tassertMsg(0, "invalid argumente type %ld\n", (uval) type); } }
char* RawAlloc(int size, int binIndex) { unsigned int val = static_cast<unsigned int>(AtomicAdd(reinterpret_cast<volatile int*>(&brk), (size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))); if (val > kHeapTop) panic("Out of heap space"); for (unsigned int addr = val; addr < val + size; addr += PAGE_SIZE) { HeapPage &page = pageDescriptors[(addr - kHeapBase) / PAGE_SIZE]; page.inUse = true; page.cleaning = false; page.binIndex = binIndex; if (binIndex < kBinCount && bins[binIndex].elementSize < PAGE_SIZE) page.freeCount = PAGE_SIZE / bins[binIndex].elementSize; else page.freeCount = 1; } return reinterpret_cast<char*>(val); }
bool Barrier::Wait() { if(0==AtomicAdd(&IsBlocking,0)) // is a barrier breaking right now { return false; } if (AtomicAdd(&ThreadCurrent,1) >= ThreadGoal-1) // { while(0!=AtomicCompareAndSwap32(&ThreadGoal,ThreadGoal,0)); AtomicAdd(&IsBlocking,-1); assert(IsBlocking==0); return true; } else { while(AtomicAdd(&IsBlocking,0)); // intentionally spinning if(1==AtomicAdd(&ThreadCurrent,-1)) { AtomicAdd(&IsBlocking,1); } return false; } }
TEST(TestAtomic, Add) { long check = STARTVAL; EXPECT_EQ(STARTVAL + 123l, AtomicAdd(&check,123l)); EXPECT_EQ(STARTVAL + 123l,check); }
virtual void Run() { for (long i = 0; i<TESTNUM; i++) AtomicAdd(number,toAdd); }
void MLTTask::Run() { PBRT_MLT_STARTED_MLT_TASK(this); // Declare basic _MLTTask_ variables and prepare for sampling PBRT_MLT_STARTED_TASK_INIT(); uint32_t nPixels = (x1-x0) * (y1-y0); uint32_t nPixelSamples = renderer->nPixelSamples; uint32_t largeStepRate = nPixelSamples / renderer->largeStepsPerPixel; Assert(largeStepRate > 1); uint64_t nTaskSamples = uint64_t(nPixels) * uint64_t(largeStepRate); uint32_t consecutiveRejects = 0; uint32_t progressCounter = progressUpdateFrequency; // Declare variables for storing and computing MLT samples MemoryArena arena; RNG rng(taskNum); vector<PathVertex> cameraPath(renderer->maxDepth, PathVertex()); vector<PathVertex> lightPath(renderer->maxDepth, PathVertex()); vector<MLTSample> samples(2, MLTSample(renderer->maxDepth)); Spectrum L[2]; float I[2]; uint32_t current = 0, proposed = 1; // Compute _L[current]_ for initial sample samples[current] = initialSample; L[current] = renderer->PathL(initialSample, scene, arena, camera, lightDistribution, &cameraPath[0], &lightPath[0], rng); I[current] = ::I(L[current]); arena.FreeAll(); // Compute randomly permuted table of pixel indices for large steps uint32_t pixelNumOffset = 0; vector<int> largeStepPixelNum; largeStepPixelNum.reserve(nPixels); for (uint32_t i = 0; i < nPixels; ++i) largeStepPixelNum.push_back(i); Shuffle(&largeStepPixelNum[0], nPixels, 1, rng); PBRT_MLT_FINISHED_TASK_INIT(); for (uint64_t s = 0; s < nTaskSamples; ++s) { // Compute proposed mutation to current sample PBRT_MLT_STARTED_MUTATION(); samples[proposed] = samples[current]; bool largeStep = ((s % largeStepRate) == 0); if (largeStep) { int x = x0 + largeStepPixelNum[pixelNumOffset] % (x1 - x0); int y = y0 + largeStepPixelNum[pixelNumOffset] / (x1 - x0); LargeStep(rng, &samples[proposed], renderer->maxDepth, x + dx, y + dy, t0, t1, renderer->bidirectional); ++pixelNumOffset; } else SmallStep(rng, &samples[proposed], renderer->maxDepth, x0, x1, y0, y1, t0, t1, renderer->bidirectional); PBRT_MLT_FINISHED_MUTATION(); // Compute contribution of proposed sample L[proposed] = renderer->PathL(samples[proposed], scene, arena, camera, lightDistribution, &cameraPath[0], &lightPath[0], rng); I[proposed] = ::I(L[proposed]); arena.FreeAll(); // Compute acceptance probability for proposed sample float a = min(1.f, I[proposed] / I[current]); // Splat current and proposed samples to _Film_ PBRT_MLT_STARTED_SAMPLE_SPLAT(); if (I[current] > 0.f) { if (!isinf(1.f / I[current])) { Spectrum contrib = (b / nPixelSamples) * L[current] / I[current]; camera->film->Splat(samples[current].cameraSample, (1.f - a) * contrib); } } if (I[proposed] > 0.f) { if (!isinf(1.f / I[proposed])) { Spectrum contrib = (b / nPixelSamples) * L[proposed] / I[proposed]; camera->film->Splat(samples[proposed].cameraSample, a * contrib); } } PBRT_MLT_FINISHED_SAMPLE_SPLAT(); // Randomly accept proposed path mutation (or not) if (consecutiveRejects >= renderer->maxConsecutiveRejects || rng.RandomFloat() < a) { PBRT_MLT_ACCEPTED_MUTATION(a, &samples[current], &samples[proposed]); current ^= 1; proposed ^= 1; consecutiveRejects = 0; } else { PBRT_MLT_REJECTED_MUTATION(a, &samples[current], &samples[proposed]); ++consecutiveRejects; } if (--progressCounter == 0) { progress.Update(); progressCounter = progressUpdateFrequency; } } Assert(pixelNumOffset == nPixels); // Update display for recently computed Metropolis samples PBRT_MLT_STARTED_DISPLAY_UPDATE(); int ntf = AtomicAdd(&renderer->nTasksFinished, 1); int64_t totalSamples = int64_t(nPixels) * int64_t(nPixelSamples); float splatScale = float(double(totalSamples) / double(ntf * nTaskSamples)); camera->film->UpdateDisplay(x0, y0, x1, y1, splatScale); if ((taskNum % 8) == 0) { MutexLock lock(*filmMutex); camera->film->WriteImage(splatScale); } PBRT_MLT_FINISHED_DISPLAY_UPDATE(); PBRT_MLT_FINISHED_MLT_TASK(this); }
virtual void recvConnection(MemTransRef mtr, XHandle otherMT) { other = otherMT; AtomicAdd(&counter,1); printf("Got message: %s from %lx\n",__func__, (uval)otherMT); Scheduler::Unblock(owner); }
uintptr_t LargeObjectCache::getCurrTimeRange(uintptr_t range) { return (uintptr_t)AtomicAdd((intptr_t&)cacheCurrTime, range)+1; }
//============================================================================ NetTrans::~NetTrans () { ASSERT(!m_link.IsLinked()); AtomicAdd(&s_perfTransCount[m_transType], -1); AtomicAdd(&s_perf[kPerfCurrTransactions], -1); // DebugMsg("%s@%p destroyed", s_transTypes[m_transType], this); }
void MLTTask::Run() { PBRT_MLT_STARTED_MLT_TASK(this); // Declare basic _MLTTask_ variables and prepare for sampling RNG rng(taskNum); MemoryArena arena; vector<MLTSample> mltSamples(2, MLTSample(maxDepth)); Spectrum sampleLs[2]; uint32_t currentSample = 0, proposedSample = 1; mltSamples[currentSample] = initialSample; sampleLs[currentSample] = L(scene, renderer, camera, arena, rng, maxDepth, ignoreDirect, mltSamples[currentSample]); int consecutiveRejects = 0; for (int sampleNum = 0; sampleNum < nSamples; ++sampleNum) { // Compute proposed mutation to current sample bool largeStep = rng.RandomFloat() < largeStepProbability; mltSamples[proposedSample] = mltSamples[currentSample]; if (largeStep) LargeStep(rng, &mltSamples[proposedSample], maxDepth, x0, x1, y0, y1, t0, t1); else SmallStep(rng, &mltSamples[proposedSample], maxDepth, x0, x1, y0, y1, t0, t1); // Compute contribution of proposed sample and acceptance probability sampleLs[proposedSample] = L(scene, renderer, camera, arena, rng, maxDepth, ignoreDirect, mltSamples[proposedSample]); float currentI = I(sampleLs[currentSample], mltSamples[currentSample]); float proposedI = I(sampleLs[proposedSample], mltSamples[proposedSample]); float a = min(1.f, proposedI / currentI); float currentWeight = (1.f - a) / (currentI / b + largeStepProbability) * float(nPixels) / float(totalSamples); float proposedWeight = (a + (largeStep ? 1.f : 0.f)) / (proposedI / b + largeStepProbability) * float(nPixels) / float(totalSamples); // Splat current and proposed samples to _Film_ if (currentWeight > 0.f && currentI > 0.f) camera->film->Splat(mltSamples[currentSample].cameraSample, sampleLs[currentSample] * currentWeight); if (proposedWeight > 0.f && proposedI > 0.f) camera->film->Splat(mltSamples[proposedSample].cameraSample, sampleLs[proposedSample] * proposedWeight); // Randomly accept proposed path mutation (or not) if (consecutiveRejects >= maxConsecutiveRejects || rng.RandomFloat() < a) { PBRT_MLT_ACCEPTED_MUTATION(a, &mltSamples[currentSample], &mltSamples[proposedSample]); currentSample ^= 1; proposedSample ^= 1; consecutiveRejects = 0; } else { PBRT_MLT_REJECTED_MUTATION(a, &mltSamples[currentSample], &mltSamples[proposedSample]); ++consecutiveRejects; } arena.FreeAll(); } // Update display for recently computed Metropolis samples float nf = AtomicAdd(nSamplesFinished, nSamples); float splatScale = float(totalSamples)/nf; camera->film->UpdateDisplay(x0, y0, x1, y1, splatScale); if ((taskNum % 32) == 0) { MutexLock lock(*filmMutex); camera->film->WriteImage(splatScale); } progress.Update(); PBRT_MLT_FINISHED_MLT_TASK(this); }
void doAdd(long* number, long toAdd) { for (long i = 0; i<TESTNUM; i++) AtomicAdd(number,toAdd); }