blob: 57ce44a63c7276e8277501943c9eb9cade835bb4 [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_NAMED_LOCK_TESTER_H_
#define PAGESPEED_KERNEL_BASE_NAMED_LOCK_TESTER_H_
#include "base/logging.h"
#include "pagespeed/kernel/base/abstract_mutex.h"
#include "pagespeed/kernel/base/basictypes.h"
#include "pagespeed/kernel/base/function.h"
#include "pagespeed/kernel/base/named_lock_manager.h"
#include "pagespeed/kernel/base/scoped_ptr.h"
#include "pagespeed/kernel/base/thread_system.h"
namespace net_instaweb {
// The NamedLock class does not have any blocking operations in it, as
// they don't fit well with PageSpeed's asynchronous archicture and with
// plans to make an asynchronous lock manager. However, in the context
// of unit tests, it is convenient to assume a blocking or schedule-based
// lock manager, and check that the call completes.
class NamedLockTester {
public:
explicit NamedLockTester(ThreadSystem* thread_system)
: acquired_(false),
failed_(false),
mutex_(thread_system->NewMutex()) {
}
bool TryLock(NamedLock* lock) {
Clear();
lock->LockTimedWait(0, MakeFunction(
this,
&NamedLockTester::LockAcquired,
&NamedLockTester::LockFailed));
Quiesce();
CHECK(WasCalled()) << "LockTimedWait returned lock operation completed";
return Acquired();
}
bool LockTimedWaitStealOld(int64 wait_ms, int64 steal_ms, NamedLock* lock) {
Clear();
lock->LockTimedWaitStealOld(wait_ms, steal_ms, MakeFunction(
this,
&NamedLockTester::LockAcquired,
&NamedLockTester::LockFailed));
Quiesce();
CHECK(WasCalled())
<< "LockTimedWaitStealOld returned lock operation completed";
return Acquired();
}
bool LockTimedWait(int64 wait_ms, NamedLock* lock) {
Clear();
lock->LockTimedWait(wait_ms, MakeFunction(
this,
&NamedLockTester::LockAcquired,
&NamedLockTester::LockFailed));
Quiesce();
CHECK(WasCalled()) << "LockTimedWait returned lock operation completed";
return Acquired();
}
void Quiesce() {
if (quiesce_.get() != NULL) {
quiesce_->CallRun();
quiesce_->Reset();
}
}
// Sets a function to be called after calling an asynchronous locking
// method, prior to testing acuisition status. Onwership of this function
// transfers to this class.
void set_quiesce(Function* quiesce) {
quiesce->set_delete_after_callback(false);
quiesce_.reset(quiesce);
}
private:
void Clear() {
ScopedMutex lock(mutex_.get());
acquired_ = false;
failed_ = false;
}
void LockAcquired() {
ScopedMutex lock(mutex_.get());
acquired_ = true;
}
void LockFailed() {
ScopedMutex lock(mutex_.get());
failed_ = true;
}
bool WasCalled() {
ScopedMutex lock(mutex_.get());
return acquired_ || failed_;
}
bool Acquired() {
ScopedMutex lock(mutex_.get());
return acquired_;
}
bool acquired_;
bool failed_;
scoped_ptr<AbstractMutex> mutex_;
scoped_ptr<Function> quiesce_;
DISALLOW_COPY_AND_ASSIGN(NamedLockTester);
};
} // namespace net_instaweb
#endif // PAGESPEED_KERNEL_BASE_NAMED_LOCK_TESTER_H_