blob: 2da8059002d009c7c15b97671741377376d68196 [file] [log] [blame]
// Copyright 2015 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: cheesy@google.com (Steve Hill)
#include "pagespeed/controller/work_bound_expensive_operation_controller.h"
namespace net_instaweb {
const char
WorkBoundExpensiveOperationController::kCurrentExpensiveOperations[] =
"current-expensive-operations";
WorkBoundExpensiveOperationController::WorkBoundExpensiveOperationController(
int max_expensive_operations, Statistics* stats)
: bound_(max_expensive_operations),
counter_(bound_ > 0 ? stats->GetUpDownCounter(kCurrentExpensiveOperations)
: NULL) {}
WorkBoundExpensiveOperationController::
~WorkBoundExpensiveOperationController() {}
void WorkBoundExpensiveOperationController::InitStats(Statistics* statistics) {
statistics->AddGlobalUpDownCounter(kCurrentExpensiveOperations);
}
bool WorkBoundExpensiveOperationController::TryToWork() {
bool can_work = true;
if (counter_ != NULL) {
// We conservatively increment, then test, and decrement on failure. This
// guarantees that two incrementors don't both get through when we're within
// 1 of the bound, at the cost of occasionally rejecting them both.
// TODO(cheesy): If Statistics ever improves its atomicity gurantees, we
// should just use the value returned by Add().
counter_->Add(1);
can_work = (counter_->Get() <= bound_);
if (!can_work) {
counter_->Add(-1);
}
}
return can_work;
}
void WorkBoundExpensiveOperationController::ScheduleExpensiveOperation(
Function* callback) {
if (TryToWork()) {
callback->CallRun();
} else {
callback->CallCancel();
}
}
void WorkBoundExpensiveOperationController::NotifyExpensiveOperationComplete() {
if (counter_ != NULL) {
counter_->Add(-1);
}
}
} // namespace net_instaweb