blob: 506e7415d790a96dffd9e7b3df6f7014df31adb2 [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;
import java.io.Closeable;
import java.util.concurrent.TimeUnit;
import org.apache.ignite.lang.IgniteCallable;
import org.apache.ignite.lang.IgniteFuture;
/**
* This interface provides a rich API for working with distributed semaphore.
* <p>
* <h1 class="header">Functionality</h1>
* Distributed semaphore provides functionality similar to {@code java.util.concurrent.Semaphore}.
* <h1 class="header">Creating Distributed Semaphore</h1>
* Instance of cache semaphore can be created by calling the following method:
* {@link Ignite#semaphore(String, int, boolean, boolean)}.
*/
public interface IgniteSemaphore extends Closeable {
/**
* Gets name of the semaphore.
*
* @return Name of the semaphore.
*/
public String name();
/**
* Acquires a permit from this semaphore, blocking until one is available, or the thread is {@linkplain
* Thread#interrupt interrupted}.
*
* <p>Acquires a permit, if one is available and returns immediately, reducing the number of available permits by
* one.
*
* <p>If no permit is available then the current thread becomes disabled for thread scheduling purposes and lies
* dormant until one of two things happens: <ul> <li>Some other thread invokes the {@link #release} method for this
* semaphore and the current thread is next to be assigned a permit; or <li>Some other thread {@linkplain
* Thread#interrupt interrupts} the current thread. </ul>
*
* <p>If the current thread: <ul> <li>has its interrupted status set on entry to this method; or <li>is {@linkplain
* Thread#interrupt interrupted} while waiting for a permit, </ul> then {@link IgniteInterruptedException} is thrown
* and the current thread's interrupted status is cleared.
*
* @throws IgniteInterruptedException if the current thread is interrupted
*/
public void acquire() throws IgniteInterruptedException;
/**
* Acquires a permit from this semaphore, blocking until one is available.
*
* <p>Acquires a permit, if one is available and returns immediately, reducing the number of available permits by
* one.
*
* <p>If no permit is available then the current thread becomes disabled for thread scheduling purposes and lies
* dormant until some other thread invokes the {@link #release} method for this semaphore and the current thread is
* next to be assigned a permit.
*
* <p>If the current thread is {@linkplain Thread#interrupt interrupted} while waiting for a permit then it will
* continue to wait, but the time at which the thread is assigned a permit may change compared to the time it would
* have received the permit had no interruption occurred. When the thread does return from this method its
* interrupt status will be set.
*/
public void acquireUninterruptibly();
/**
* Acquires a permit from this semaphore, only if one is available at the time of invocation.
*
* <p>Acquires a permit, if one is available and returns immediately, with the value {@code true}, reducing the
* number of available permits by one.
*
* <p>If no permit is available then this method will return immediately with the value {@code false}.
*
* @return {@code true} if a permit was acquired and {@code false} otherwise
*/
public boolean tryAcquire();
/**
* Acquires a permit from this semaphore, if one becomes available within the given waiting time and the current
* thread has not been {@linkplain Thread#interrupt interrupted}.
*
* <p>Acquires a permit, if one is available and returns immediately, with the value {@code true}, reducing the
* number of available permits by one.
*
* <p>If no permit is available then the current thread becomes disabled for thread scheduling purposes and lies
* dormant until one of three things happens: <ul> <li>Some other thread invokes the {@link #release} method for
* this semaphore and the current thread is next to be assigned a permit; or <li>Some other thread {@linkplain
* Thread#interrupt interrupts} the current thread; or <li>The specified waiting time elapses. </ul>
*
* <p>If a permit is acquired then the value {@code true} is returned.
*
* <p>If the current thread: <ul> <li>has its interrupted status set on entry to this method; or <li>is {@linkplain
* Thread#interrupt interrupted} while waiting to acquire a permit, </ul> then {@link IgniteInterruptedException} is
* thrown and the current thread's interrupted status is cleared.
*
* <p>If the specified waiting time elapses then the value {@code false} is returned. If the time is less than or
* equal to zero, the method will not wait at all.
*
* @param timeout the maximum time to wait for a permit
* @param unit the time unit of the {@code timeout} argument
* @return {@code true} if a permit was acquired and {@code false} if the waiting time elapsed before a permit was
* acquired
* @throws IgniteInterruptedException if the current thread is interrupted
*/
public boolean tryAcquire(long timeout, TimeUnit unit)
throws IgniteInterruptedException;
/**
* Acquires the given number of permits from this semaphore, blocking until all are available.
*
* <p>Acquires the given number of permits, if they are available, and returns immediately, reducing the number of
* available permits by the given amount.
*
* <p>If insufficient permits are available then the current thread becomes disabled for thread scheduling purposes
* and lies dormant until some other thread invokes one of the {@link #release() release} methods for this
* semaphore, the current thread is next to be assigned permits and the number of available permits satisfies this
* request.
*
* <p>If the current thread is {@linkplain Thread#interrupt interrupted} while waiting for permits then it will
* continue to wait and its position in the queue is not affected. When the thread does return from this method its
* interrupt status will be set.
*
* @param permits the number of permits to acquire
* @throws IllegalArgumentException if {@code permits} is negative
*/
public void acquireUninterruptibly(int permits);
/**
* Returns the current number of permits available in this semaphore.
*
* <p>This method is typically used for debugging and testing purposes.
*
* @return the number of permits available in this semaphore
*/
public int availablePermits();
/**
* Acquires and returns all permits that are immediately available.
*
* @return the number of permits acquired
*/
public int drainPermits();
/**
* Releases a permit, returning it to the semaphore.
*
* <p>Releases a permit, increasing the number of available permits by one. If any threads are trying to acquire a
* permit, then one is selected and given the permit that was just released. That thread is (re)enabled for thread
* scheduling purposes.
*
* <p>There is no requirement that a thread that releases a permit must have acquired that permit by calling {@link
* #acquire}. Correct usage of a semaphore is established by programming convention in the application.
*/
public void release();
/**
* Acquires the given number of permits from this semaphore, if all become available within the given waiting time
* and the current thread has not been {@linkplain Thread#interrupt interrupted}.
*
* <p>Acquires the given number of permits, if they are available and returns immediately, with the value {@code
* true}, reducing the number of available permits by the given amount.
*
* <p>If insufficient permits are available then the current thread becomes disabled for thread scheduling purposes
* and lies dormant until one of three things happens: <ul> <li>Some other thread invokes one of the {@link
* #release() release} methods for this semaphore, the current thread is next to be assigned permits and the number
* of available permits satisfies this request; or <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread; or <li>The specified waiting time elapses. </ul>
*
* <p>If the permits are acquired then the value {@code true} is returned.
*
* <p>If the current thread: <ul> <li>has its interrupted status set on entry to this method; or <li>is {@linkplain
* Thread#interrupt interrupted} while waiting to acquire the permits, </ul> then {@link IgniteInterruptedException}
* is thrown and the current thread's interrupted status is cleared. Any permits that were to be assigned to this
* thread, are instead assigned to other threads trying to acquire permits, as if the permits had been made
* available by a call to {@link #release()}.
*
* <p>If the specified waiting time elapses then the value {@code false} is returned. If the time is less than or
* equal to zero, the method will not wait at all. Any permits that were to be assigned to this thread, are instead
* assigned to other threads trying to acquire permits, as if the permits had been made available by a call to
* {@link #release()}.
*
* @param permits the number of permits to acquire
* @param timeout the maximum time to wait for the permits
* @param unit the time unit of the {@code timeout} argument
* @return {@code true} if all permits were acquired and {@code false} if the waiting time elapsed before all
* permits were acquired
* @throws IgniteInterruptedException if the current thread is interrupted
* @throws IllegalArgumentException if {@code permits} is negative
*/
public boolean tryAcquire(int permits, long timeout, TimeUnit unit)
throws IgniteInterruptedException;
/**
* Acquires the given number of permits from this semaphore, only if all are available at the time of invocation.
*
* <p>Acquires the given number of permits, if they are available, and returns immediately, with the value {@code
* true}, reducing the number of available permits by the given amount.
*
* <p>If insufficient permits are available then this method will return immediately with the value {@code false}
* and the number of available permits is unchanged.
*
* <p>If you want to honor the failoverSafe setting, then use {@link #tryAcquire(int, long, TimeUnit)
* tryAcquire(permits, 0, TimeUnit.SECONDS) } which is almost equivalent (it also detects interruption).
*
* @param permits the number of permits to acquire
* @return {@code true} if the permits were acquired and {@code false} otherwise
* @throws IllegalArgumentException if {@code permits} is negative
*/
public boolean tryAcquire(int permits);
/**
* Acquires the given number of permits from this semaphore, blocking until all are available, or the thread is
* {@linkplain Thread#interrupt interrupted}.
*
* <p>Acquires the given number of permits, if they are available, and returns immediately, reducing the number of
* available permits by the given amount.
*
* <p>If insufficient permits are available then the current thread becomes disabled for thread scheduling purposes
* and lies dormant until one of two things happens: <ul> <li>Some other thread invokes one of the {@link #release()
* release} methods for this semaphore, the current thread is next to be assigned permits and the number of
* available permits satisfies this request; or <li>Some other thread {@linkplain Thread#interrupt interrupts} the
* current thread. </ul>
*
* <p>If the current thread: <ul> <li>has its interrupted status set on entry to this method; or <li>is {@linkplain
* Thread#interrupt interrupted} while waiting for a permit, </ul> then {@link IgniteInterruptedException} is thrown
* and the current thread's interrupted status is cleared. Any permits that were to be assigned to this thread are
* instead assigned to other threads trying to acquire permits, as if permits had been made available by a call to
* {@link #release()}.
*
* @param permits the number of permits to acquire
* @throws IgniteInterruptedException if the current thread is interrupted
* @throws IllegalArgumentException if {@code permits} is negative
*/
public void acquire(int permits) throws IgniteInterruptedException;
/**
* Acquires the given semaphore, executes the given callable and schedules the release of permits asynchronously
*
* @param callable the callable to execute
* @param numPermits the number of permits to acquire
* @param <T> Type of the callable execution result.
* @return Callable execution future.
* @throws Exception if the callable throws an exception
*/
public <T> IgniteFuture<T> acquireAndExecute(IgniteCallable<T> callable,
int numPermits) throws Exception;
/**
* Releases the given number of permits, returning them to the semaphore.
*
* <p>Releases the given number of permits, increasing the number of available permits by that amount. If any
* threads are trying to acquire permits, then one is selected and given the permits that were just released. If the
* number of available permits satisfies that thread's request then that thread is (re)enabled for thread scheduling
* purposes; otherwise the thread will wait until sufficient permits are available. If there are still permits
* available after this thread's request has been satisfied, then those permits are assigned in turn to other
* threads trying to acquire permits.
*
* <p>There is no requirement that a thread that releases a permit must have acquired that permit by calling {@link
* IgniteSemaphore#acquire acquire}. Correct usage of a semaphore is established by programming convention in the
* application.
*
* @param permits the number of permits to release
* @throws IllegalArgumentException if {@code permits} is negative
*/
public void release(int permits);
/**
* Returns {@code true} if this semaphore is safe to use after node failure.
* If not, IgniteInterruptedException is thrown on every other node after node failure.
*
* @return {@code true} if this semaphore has failoverSafe set true
*/
public boolean isFailoverSafe();
/**
* Queries whether any threads are waiting to acquire. Note that because cancellations may occur at any time, a
* {@code true} return does not guarantee that any other thread will ever acquire. This method is designed
* primarily for use in monitoring of the system state.
*
* @return {@code true} if there may be other threads waiting to acquire the lock
*/
public boolean hasQueuedThreads();
/**
* Returns an estimate of the number of nodes waiting to acquire. The value is only an estimate because the number
* of nodes that are waiting may change dynamically while this method traverses internal data structures. This method is designed
* for use in monitoring of the system state, not for synchronization control.
*
* @return the estimated number of nodes waiting for this lock
*/
public int getQueueLength();
/**
* Gets {@code broken} status of the semaphore.
*
* @return {@code True} if a node failed on this semaphore and failoverSafe flag was set to false, {@code false} otherwise.
*/
public boolean isBroken();
/**
* Gets {@code removed} status of the semaphore.
*
* @return {@code True} if semaphore was removed from cache, {@code false} otherwise.
*/
public boolean removed();
/**
* Removes this semaphore.
*
* @throws IgniteException If operation failed.
*/
@Override public void close();
}