| 2401 | |
| 2402 | |
| 2403 | void Resources::subtract(const Resource_& that) |
| 2404 | { |
| 2405 | if (that.isEmpty()) { |
| 2406 | return; |
| 2407 | } |
| 2408 | |
| 2409 | for (size_t i = 0; i < resourcesNoMutationWithoutExclusiveOwnership.size(); |
| 2410 | i++) { |
| 2411 | Resource_Unsafe& resource_ = |
| 2412 | resourcesNoMutationWithoutExclusiveOwnership[i]; |
| 2413 | |
| 2414 | if (internal::subtractable(resource_->resource, that)) { |
| 2415 | // Copy-on-write (if more than 1 reference). |
| 2416 | if (resource_.use_count() > 1) { |
| 2417 | resource_ = make_shared<Resource_>(*resource_); |
| 2418 | } |
| 2419 | |
| 2420 | *resource_ -= that; |
| 2421 | |
| 2422 | // Remove the resource if it has become negative or empty. |
| 2423 | // Note that a negative resource means the caller is |
| 2424 | // subtracting more than they should! |
| 2425 | // |
| 2426 | // TODO(gyliu513): Provide a stronger interface to avoid |
| 2427 | // silently allowing this to occur. |
| 2428 | |
| 2429 | // A "negative" Resource_ either has a negative sharedCount or |
| 2430 | // a negative scalar value. |
| 2431 | bool negative = |
| 2432 | (resource_->isShared() && resource_->sharedCount.get() < 0) || |
| 2433 | (resource_->resource.type() == Value::SCALAR && |
| 2434 | resource_->resource.scalar().value() < 0); |
| 2435 | |
| 2436 | if (negative || resource_->isEmpty()) { |
| 2437 | // As `resources` is not ordered, and erasing an element |
| 2438 | // from the middle is expensive, we swap with the last element |
| 2439 | // and then shrink the vector by one. |
| 2440 | resourcesNoMutationWithoutExclusiveOwnership[i] = |
| 2441 | resourcesNoMutationWithoutExclusiveOwnership.back(); |
| 2442 | resourcesNoMutationWithoutExclusiveOwnership.pop_back(); |
| 2443 | } |
| 2444 | |
| 2445 | break; |
| 2446 | } |
| 2447 | } |
| 2448 | } |
| 2449 | |
| 2450 | |
| 2451 | Resources& Resources::operator-=(const Resource_& that) |