void Tipsify::operator()(std::size_t cacheSize) { /* Neighboring triangles for each vertex, per-vertex live triangle count */ std::vector<UnsignedInt> liveTriangleCount, neighborPosition, neighbors; buildAdjacency(liveTriangleCount, neighborPosition, neighbors); /* Global time, per-vertex caching timestamps, per-triangle emmited flag */ UnsignedInt time = cacheSize+1; std::vector<UnsignedInt> timestamp(vertexCount); std::vector<bool> emitted(indices.size()/3); /* Dead-end vertex stack */ std::stack<UnsignedInt> deadEndStack; /* Output index buffer */ std::vector<UnsignedInt> outputIndices; outputIndices.reserve(indices.size()); /* Starting vertex for fanning, cursor */ UnsignedInt fanningVertex = 0; UnsignedInt i = 0; while(fanningVertex != 0xFFFFFFFFu) { /* Array with candidates for next fanning vertex (in 1-ring around fanning vertex) */ std::vector<UnsignedInt> candidates; /* For all neighbors of fanning vertex */ for(UnsignedInt ti = neighborPosition[fanningVertex], t = neighbors[ti]; ti != neighborPosition[fanningVertex+1]; t = neighbors[++ti]) { /* Continue if already emitted */ if(emitted[t]) continue; emitted[t] = true; /* Write all vertices of the triangle to output buffer */ for(UnsignedInt vi = 0; vi != 3; ++vi) { const UnsignedInt v = indices[vi + t*3]; outputIndices.push_back(v); /* Add to dead end stack and candidates array */ /** @todo Limit size of dead end stack to cache size */ deadEndStack.push(v); candidates.push_back(v); /* Decrease live triangle count */ --liveTriangleCount[v]; /* If not in cache, set timestamp */ if(time-timestamp[v] > cacheSize) timestamp[v] = time++; } } /* Get next fanning vertex */ fanningVertex = 0xFFFFFFFFu; /* Go through candidates in 1-ring around fanning vertex */ Int candidatePriority = -1; for(UnsignedInt v: candidates) { /* Skip if it doesn't have any live triangles */ if(!liveTriangleCount[v]) continue; /* Get most fresh candidate which will still be in cache even after fanning. Every fanned triangle will generate at most two cache misses, thus 2*liveTriangleCount */ Int priority = 0; if(time-timestamp[v]+2*liveTriangleCount[v] <= cacheSize) priority = time-timestamp[v]; if(priority > candidatePriority) { fanningVertex = v; candidatePriority = priority; } } /* On dead-end */ if(fanningVertex == 0xFFFFFFFFu) { /* Find vertex with live triangles in dead-end stack */ while(!deadEndStack.empty()) { unsigned int d = deadEndStack.top(); deadEndStack.pop(); if(!liveTriangleCount[d]) continue; fanningVertex = d; break; } /* If not found, find next artbitrary vertex with live triangles */ while(++i < vertexCount) { if(!liveTriangleCount[i]) continue; fanningVertex = i; break; } } } /* Swap original index buffer with optimized */ std::swap(indices, outputIndices); }
bool AkonadiServer::init() { connect(watcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)), this, SLOT(serviceOwnerChanged(QString,QString,QString))); return true; } connect(&mapper, SIGNAL(mapped(Q1&)), this, SLOT(onSomeEvent(const Q2&))); connect(&mapper, SIGNAL(mapped(Q1&)), this, SLOT(onSomeEvent(const Q2&))); connect(&mapper, SIGNAL(emitted(Q1*)), this, SLOT(accept(const Q2*))); connect(&mapper, SIGNAL(emitted(X<int>)), this, SLOT(accept(X<int>)));