blob: 06a9d48e6ed91d5549d32247eac08c2aee59b2ca [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.apache.ignite.internal.util;
import java.util.concurrent.TimeUnit;
/**
* Synchronization aid to track "busy" state of a subsystem that owns it.
* <p>
* This class is implemented
* over {@link IgniteSpinReadWriteLock}.
* <p>
* For example, there may be a manager that have different threads for some
* purposes and the manager must not be stopped while at least a single thread
* is in "busy" state. In this situation each thread must enter to "busy"
* state calling method {@link #enterBusy()} in critical pieces of code
* which, i.e. use grid kernal functionality, notifying that the manager
* and the whole grid kernal cannot be stopped while it's in progress. Once
* the activity is done, the thread should leave "busy" state calling method
* {@link #leaveBusy()}. The manager itself, when stopping, should call method
* {@link #block} that blocks till all activities leave "busy" state.
* @see IgniteSpinReadWriteLock
*/
public class IgniteSpinBusyLock {
/** Underlying read-write lock. */
private final IgniteSpinReadWriteLock lock = new IgniteSpinReadWriteLock();
/**
* Enters "busy" state.
*
* @return {@code true} if entered to busy state.
*/
public boolean enterBusy() {
return !lock.writeLockedByCurrentThread() && lock.tryReadLock();
}
/**
* Checks if busy lock was blocked by current thread.
*
* @return {@code True} if busy lock was blocked by current thread.
*/
public boolean blockedByCurrentThread() {
return lock.writeLockedByCurrentThread();
}
/**
* Leaves "busy" state.
*/
public void leaveBusy() {
lock.readUnlock();
}
/**
* Blocks current thread till all activities left "busy" state
* and prevents them from further entering to "busy" state.
*/
public void block() {
lock.writeLock();
}
/**
* @param millis Timeout.
* @return {@code True} if lock was acquired.
* @throws InterruptedException If interrupted.
*/
public boolean tryBlock(long millis) throws InterruptedException {
return lock.tryWriteLock(millis, TimeUnit.MILLISECONDS);
}
/**
* Makes possible for activities entering busy state again.
*/
public void unblock() {
lock.writeUnlock();
}
}