blob: 2d26620cad053c4cd64d0ed608f7d156342f41e1 [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: jmarantz@google.com (Joshua Marantz)
#ifndef PAGESPEED_KERNEL_BASE_MEM_LOCK_H_
#define PAGESPEED_KERNEL_BASE_MEM_LOCK_H_
#include <map>
#include <set>
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/named_lock_manager.h"
#include "pagespeed/kernel/base/string.h"
#include "pagespeed/kernel/base/string_util.h"
#include "pagespeed/kernel/base/timer.h"
namespace net_instaweb {
class MemLockState;
class MemLock : public NamedLock {
public:
static const int64 kDoNotSteal = -1;
static const int64 kNotHeld = -1;
static const int64 kNotPending = -1;
virtual void LockTimedWait(int64 wait_ms, Function* callback);
virtual void LockTimedWaitStealOld(int64 wait_ms, int64 steal_ms,
Function* callback);
virtual void Unlock();
virtual GoogleString name() const;
virtual bool Held() { return grant_time_ms_ != kNotHeld; }
// Entry-point for the lock-manager to wake up this lock, stealing it or
// canceling as needed.
void Wakeup();
// Returns the currently scheduled time of the next required wakeup for this
// lock, based on the earlier cancel timeout and time it gets to steal the
// lock that is currently held. Note that this value can be changed by
// CalculateWakeupTime, This value is in absolute time since 1970.
int64 wakeup_time_ms() const { return wakeup_time_ms_; }
// Computes a stable ordering for multiple locks with the same
// time-based criteria based primarily on the name, and secondarily on
// the sequence number.
//
// Returns -1 if this is less than that.
// Returns 1 if this is greater than that.
// Check-fails if they compare as the same.
int StableCompare(const MemLock* that) const;
private:
friend class MemLockState;
// Only MemLockState can construct MemLocks.
MemLock(int64 sequence, MemLockState* lock_state);
virtual ~MemLock();
// The time this lock was granted, or kNotHeld if not held.
int64 grant_time_ms() const { return grant_time_ms_; }
// Returns the number of maximum number of milliseconds that the current
// lock can hold prior to this lock stealing it. This value is relative
// to the start of the holding lock.
int64 steal_ms() const { return steal_ms_; }
// Grants a lock, calling the callback's Run method. It is invalid
// to attempt to grant a lock when it is already held, or is not pending.
void Grant(int64 grant_time_ms);
// Denies a lock, calling the callback's Cancel methods. It is
// invalid to attempt to Deny a lock when it is already held, or is
// not pending.
void Deny();
// Determines what the next wakeup time for this lock is, which is the
// earlier of the cancel timeout and the steal-time based on the time
// since the currently holding lock was granted.
//
// Note that if a lock is in a time-ordered set this is invalid to call,
// and will likely cause a crash.
//
// If no there is no holding lock, held_lock_grant_time_ms should be specified
// as kNotHeld.
void CalculateWakeupTime(int64 held_lock_grant_time_ms);
// Determines whether this lock is configured to steal from others.
bool CanSteal() const { return steal_ms_ != kDoNotSteal; }
// Determines whether this lock has been requested, but not yet granted.
bool IsPending() const { return wakeup_time_ms_ != kNotPending; }
// Clears out all lock state. This is invalid to call when the lock is
// in any kind of set.
void Clear();
// Determines whether this lock should be cancelled if it is woken
// up before it is granted.
bool ShouldCancelOnWakeup() const {
return cancel_time_ms_ == wakeup_time_ms_;
}
MemLockState* lock_state_;
Function* callback_;
int64 cancel_time_ms_; // Absolute (MS since 1970)
int64 grant_time_ms_; // Absolute time lock was granted, or kNotHeld.
int64 sequence_; // Lock index assigned by MemLockManager.
// Only mutate steal_ms_ and wakeup_time_ms_ when !lock_state_->IsPending()
// since that would corrupt maps in lock_state_ and lock_state_->manager_.
int64 steal_ms_; // Relative.
int64 wakeup_time_ms_; // Absolute, and may be canceling or stealing.
};
} // namespace net_instaweb
#endif // PAGESPEED_KERNEL_BASE_MEM_LOCK_H_