| 2368 | |
| 2369 | |
| 2370 | void Resources::subtract(const Resource_& that) |
| 2371 | { |
| 2372 | if (that.isEmpty()) { |
| 2373 | return; |
| 2374 | } |
| 2375 | |
| 2376 | for (size_t i = 0; i < resourcesNoMutationWithoutExclusiveOwnership.size(); |
| 2377 | i++) { |
| 2378 | Resource_Unsafe& resource_ = |
| 2379 | resourcesNoMutationWithoutExclusiveOwnership[i]; |
| 2380 | |
| 2381 | if (internal::subtractable(resource_->resource, that)) { |
| 2382 | // Copy-on-write (if more than 1 reference). |
| 2383 | if (resource_.use_count() > 1) { |
| 2384 | resource_ = make_shared<Resource_>(*resource_); |
| 2385 | } |
| 2386 | |
| 2387 | *resource_ -= that; |
| 2388 | |
| 2389 | // Remove the resource if it has become negative or empty. |
| 2390 | // Note that a negative resource means the caller is |
| 2391 | // subtracting more than they should! |
| 2392 | // |
| 2393 | // TODO(gyliu513): Provide a stronger interface to avoid |
| 2394 | // silently allowing this to occur. |
| 2395 | |
| 2396 | // A "negative" Resource_ either has a negative sharedCount or |
| 2397 | // a negative scalar value. |
| 2398 | bool negative = |
| 2399 | (resource_->isShared() && resource_->sharedCount.get() < 0) || |
| 2400 | (resource_->resource.type() == Value::SCALAR && |
| 2401 | resource_->resource.scalar().value() < 0); |
| 2402 | |
| 2403 | if (negative || resource_->isEmpty()) { |
| 2404 | // As `resources` is not ordered, and erasing an element |
| 2405 | // from the middle is expensive, we swap with the last element |
| 2406 | // and then shrink the vector by one. |
| 2407 | resourcesNoMutationWithoutExclusiveOwnership[i] = |
| 2408 | resourcesNoMutationWithoutExclusiveOwnership.back(); |
| 2409 | resourcesNoMutationWithoutExclusiveOwnership.pop_back(); |
| 2410 | } |
| 2411 | |
| 2412 | break; |
| 2413 | } |
| 2414 | } |
| 2415 | } |
| 2416 | |
| 2417 | |
| 2418 | Resources& Resources::operator-=(const Resource_& that) |