void produce (const Producer & producer) { LOOM_DEBUG_QUEUE("produce " << (position_ % size_plus_one_)); LOOM_ASSERT2(size_plus_one_ > 1, "cannot use zero-length queue"); const Envelope & fence = envelopes(position_ + 1); guards_[stage_count_].acquire(fence.state); Envelope & envelope = envelopes(position_); producer(envelope.message); guards_[0].release(envelope.state); position_ += 1; }
void wait () { LOOM_DEBUG_QUEUE("wait at " << (position_ % size_plus_one_)); Envelope & last_to_finish = envelopes(position_ + size_plus_one_ - 1); guards_[stage_count_].acquire(last_to_finish.state); assert_ready(); }
void consume ( size_t stage_number, size_t position, const Consumer & consumer) { LOOM_DEBUG_QUEUE("consume " << stage_number << " " << (position % size_plus_one_)); LOOM_ASSERT2(size_plus_one_ > 1, "cannot use zero-length queue"); LOOM_ASSERT2(stage_number < stage_count_, "bad stage number: " << stage_number); Envelope & envelope = envelopes(position); guards_[stage_number].acquire(envelope.state); consumer(envelope.message); guards_[stage_number + 1].release(envelope.state); }
void ConvexPolygon::booleanDifference(const ConvexPolygon &hole, std::vector<ConvexPolygon> &list) const { // Special case: this polygon is entirely swallowed by the hole if(hole.envelopes(*this)) return; // Special case: the hole is entirely inside this polygon if(envelopes(hole)) { Points p1, p2; splitPolygon(*this, hole, p1, p2); ConvexPolygon::make(p1, list); ConvexPolygon::make(p2, list); return; } // Common case: hole intersects with this polygon. std::vector<bool> visited(vertexCount()); std::queue<unsigned int> queue; queue.push(0); // Perform intersection unsigned int oldsize = list.size(); Points poly; while(!queue.empty()) { int i = queue.front(); while(i < vertexCount()) { // Stop if we've already been here if(visited[i]) break; visited[i] = true; // Include point if it is not inside the hole bool inhole = hole.hasPoint(vertex(i)); if(!inhole) poly.push_back(vertex(i)); // Check for intersections Point isect[2]; int isectv[2]; findIntersections(*this, i, i+1, hole, isect, isectv); if(isectv[0] >= 0) { // Intersection found: this is the start of a hole, // except when this edge started inside the hole. poly.push_back(isect[0]); if(!inhole) { // Start tracing the hole int j = isectv[0]; do { // Check for intersections // The first hole edge may intersect with another edges Point hisect[2]; int hisectv[2]; findIntersections(hole, j+1, j, *this, hisect, hisectv); // There is always one intersection (the one that got us here) if((j == isectv[0] && hisectv[1] >= 0) || (j != isectv[0] && hisectv[0] >= 0)) { // Pick the intersection that is not the one we came in on Point ip; int iv; if(hisectv[1] < 0 || glm::distance2(hisect[0],isect[0]) > glm::distance(hisect[1],isect[0])) { ip = hisect[0]; iv = hisectv[0]; } else { ip = hisect[1]; iv = hisectv[1]; } queue.push(i+1); // Avoid adding duplicate point of origin if(glm::distance2(poly.front(), ip) > 0.0001) poly.push_back(ip); i = iv; break; } else { // No intersections? Just add the hole vertex then poly.push_back(hole.vertex(j)); } if(--j < 0) j = hole.vertexCount() - 1; } while(j != isectv[0]); } } ++i; } // Partition the generated polygon into convex polygons // and add them to the list. if(poly.size() >= 3) { try { ConvexPolygon::make(poly, list); } catch(const algorithm::GeometryException &e) { // Bad polygons generated... The algorithm works well // enough most of the time, let's just roll back the error. int changes = list.size() - oldsize; #ifndef NDEBUG cerr << "booleanDifference error: " << e.what() << " (" << changes << " change(s) rolled back)\n"; #endif while(changes-->0) list.pop_back(); list.push_back(*this); return; } } poly.clear(); queue.pop(); } }