| /* |
| * 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: jmarantz@google.com (Joshua Marantz) |
| |
| #include "pagespeed/kernel/util/mem_lock_manager.h" |
| |
| #include "pagespeed/kernel/base/function.h" |
| #include "pagespeed/kernel/base/timer.h" |
| #include "pagespeed/kernel/util/mem_lock.h" |
| #include "pagespeed/kernel/util/mem_lock_state.h" |
| |
| namespace net_instaweb { |
| |
| MemLockManager::MemLockManager(Timer* timer) |
| : timer_(timer), |
| sequence_(0) { |
| } |
| |
| MemLockManager::~MemLockManager() { |
| // Note that we don't delete the locks here. We just detach the |
| // MemLockState objects. The MemLockState objects need to outlive |
| // all the MemLocks allocated against them, as they are dependent |
| // on the MemLockState to know their own name. |
| for (MemLockStateMap::iterator p = lock_state_map_.begin(), |
| e = lock_state_map_.end(); p != e; ++p) { |
| MemLockState* name_state = p->second; |
| name_state->MemLockManagerDestroyed(); |
| } |
| } |
| |
| void MemLockManager::RemoveLockState(MemLockState* name_state) { |
| int erased = lock_state_map_.erase(name_state->name()); |
| CHECK_EQ(1, erased); |
| } |
| |
| NamedLock* MemLockManager::CreateNamedLock(const StringPiece& name) { |
| MemLockStateMap::iterator p = lock_state_map_.find(name); |
| MemLockState* mem_lock_state; |
| if (p != lock_state_map_.end()) { |
| mem_lock_state = p->second; |
| } else { |
| // Make sure that the StringPiece held as the map key points to |
| // the MemLockState, and not the possibly temporary char* passed |
| // in as name.data(). |
| mem_lock_state = new MemLockState(name, this); |
| lock_state_map_[mem_lock_state->name()] = mem_lock_state; |
| } |
| return mem_lock_state->CreateLock(++sequence_); |
| } |
| |
| void MemLockManager::AddPendingLock(MemLock* lock) { |
| pending_locks_.insert(lock); |
| } |
| |
| void MemLockManager::RemovePendingLock(MemLock* lock) { |
| pending_locks_.erase(lock); |
| } |
| |
| int64 MemLockManager::NextWakeupTimeMs() const { |
| if (pending_locks_.empty()) { |
| return kNoWakeupsPending; |
| } |
| MemLock* next_lock = *pending_locks_.begin(); |
| return next_lock->wakeup_time_ms(); |
| } |
| |
| void MemLockManager::Wakeup() { |
| int64 now_ms = timer_->NowMs(); |
| while (!pending_locks_.empty()) { |
| MemLockState::WakeupOrderedLockSet::iterator p = pending_locks_.begin(); |
| MemLock* lock = *p; |
| if (lock->wakeup_time_ms() <= now_ms) { |
| lock->Wakeup(); |
| } else { |
| return; |
| } |
| } |
| } |
| |
| bool MemLockManager::IsHeldInOrderedSet(MemLock* lock) const { |
| return pending_locks_.find(lock) != pending_locks_.end(); |
| } |
| |
| } // namespace net_instaweb |