All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jtrim2.access.AccessManager Maven / Gradle / Ivy

package org.jtrim2.access;

import java.util.Collection;
import org.jtrim2.event.ListenerRef;

/**
 * Manages read and write access to resources. A certain access right
 * is represented by an {@link AccessToken} which allows tasks to be
 * executed on a certain {@code TaskExecutor}. The {@code TaskExecutor} will
 * only execute tasks until the right associated with the given
 * {@code AccessToken}.
 * 

* No {@code AccessToken}s provided by an {@code AccessManager} can be * conflicting and simultaneously being active (i.e.: not released). *

    *
  1. Two {@code AccessToken}s are said to be conflicting if their right * requests conflict.
  2. *
  3. Two access requests are said to be conflicting if they contain conflicting * rights.
  4. *
  5. Two rights are said to be conflicting if their domains intersect and * at least one of them is a write request. * rights.
  6. *
  7. If the domain of rights intersect or not is defined by the implementation * of the {@code AccessManager}.
  8. *
* Notice that two read request can never conflict. *

* Note that {@code AccessManager} was not designed to protect from * malicious access to a resource. The intended use of this class * is to allow cooperating codes to access resources that cannot be accessed * concurrently. Anyone may shuts down {@code AccessToken}s to gain access * to a resource and the specification of this interface does not allow * an implementation to refuse such a request. However it may fail to * shut down an {@code AccessToken} if the {@code AccessToken} is currently * executing a task. *

Thread safety

* Instances of this interface are required to be completely thread-safe * without any further synchronization. *

Synchronization transparency

* The methods of this class are not required to be * synchronization transparent. * * @param the type of the request ID (see * {@link AccessRequest#getRequestID()}) * @param the type of the rights that can be managed by the * {@code AccessManager} * * @see AccessManagers * @see AccessToken * @see HierarchicalAccessManager */ public interface AccessManager { /** * Adds a new listener which is to be notified whenever a new access token * is acquired or released. The listeners are notified in the order these * events occur. That is, if an event (A) happens before another event (B), * then the notification of the registered listeners reporting the event A, * happens before reporting the event B. *

* The listener can be removed by calling the * {@link ListenerRef#unregister() unregister} method of the returned * reference. * * @param listener the listener to be notified whenever a new access token * is acquired or released. This argument cannot be {@code null}. * @return the {@code ListenerRef} which can be used to remove the currently * added listener. This method never returns {@code null}. * * @throws NullPointerException thrown if the specified listener is * {@code null} */ public ListenerRef addAccessChangeListener(AccessChangeListener listener); /** * Returns the {@link AccessToken AccessTokens} which conflicts the * given read and write right request. *

* If no other right requests were made during and after this call * shutting down these {@code AccessToken}s will allow the caller * to immediately acquire the requested rights. *

* The following method prints the {@code AccessToken}s blocking a given * right request: *

{@code
     *  void printConflicts(
     *     AccessManager manager,
     *     AccessRequest request) {
     *   Collection conflicts = manager.getBlockingTokens(
     *     request.getReadRights(),
     *     request.getWriteRights());
     *
     *   if (conflicts.isEmpty()) {
     *     System.out.println("There are no conflicts.");
     *   }
     *   else {
     *     System.out.println("Conflicts: " + conflicts);
     *   }
     * }
     * }
*

* Note that the returned tokens may conflict because they may contain * tokens that were not yet returned by a * {@link #getScheduledAccess(AccessRequest)} call. * * @param requestedReadRights the required read rights. This argument * cannot be {@code null} but can be an empty {@code Collection}. * @param requestedWriteRights the required write rights. This argument * cannot be {@code null} but can be an empty {@code Collection}. * @return the {@code AccessToken}s needed to be shutted down before * being able to acquire the required rights. This method never returns * {@code null}. * * @throws NullPointerException thrown if one of the arguments is * {@code null} * * @see #isAvailable(Collection, Collection) */ public Collection> getBlockingTokens( Collection requestedReadRights, Collection requestedWriteRights); /** * Checks if the given rights are currently available for an access request. * That is, if this method returns {@code true}, a subsequent * {@code tryGetAccess} will succeed unless new access is requested before * the {@code tryGetAccess}. *

* This method returns {@code true}, if and only, if the * {@link #getBlockingTokens(Collection, Collection) getBlockingTokens} * method call would have returned an empty {@code Collection}. * * @param requestedReadRights the required read rights. This argument * cannot be {@code null} but can be an empty {@code Collection}. * @param requestedWriteRights the required write rights. This argument * cannot be {@code null} but can be an empty {@code Collection}. * @return {@code true} if the specified rights are available at the moment, * {@code false} if not * * @throws NullPointerException thrown if one of the arguments is * {@code null} * * @see #getBlockingTokens(Collection, Collection) */ public boolean isAvailable( Collection requestedReadRights, Collection requestedWriteRights); /** * Tries to acquire the requested rights and returns immediately if it * cannot be acquired without waiting and/or releasing * {@link AccessToken AccessTokens}. The returned access token will use * the default executor to execute tasks submitted to it. This method never * waits for tasks to complete and always returns immediately. *

* This method either returns an {@code AccessToken} representing the * requested rights or the list of {@code AccessToken}s required to be * shutted down before such request can be granted. Note that even if the * request could have been granted the returned {@code AccessToken} can * already be released when the caller wants to use it. *

* The following method executes a task using a given right request * or prints the conflicting {@code AccessToken}s if it cannot be * done immediately: *

{@code
     *  void tryExecuteTask(
     *     AccessManager manager,
     *     TaskExecutor executor,
     *     AccessRequest request
     *     CancelableTask task) {
     *   AccessResult result = manager.tryGetAccess(request);
     *
     *   if (result.isAvailable()) {
     *     TaskExecutor tokenExecutor = result.getAccessToken().createExecutor(executor);
     *     tokenExecutor.execute(Cancellation.UNCANCELABLE_TOKEN, task);
     *   }
     *   else {
     *     System.out.println("Conflicts: " + result.getBlockingTokens());
     *   }
     * }
     * }
* Note that the returned blocking tokens (those conflicting with the * requested rights) may conflict because they may contain tokens that were * returned by a {@link #getScheduledAccess(AccessRequest)} call. * * @param request the rights to be requested. This argument cannot be * {@code null}. * @return the {@code AccessToken} if the request could be granted or * the list of {@code AccessToken}s that needed to be shut down before * the request can be granted. This method never returns {@code null}. * * @throws NullPointerException thrown if the request is {@code null} */ public AccessResult tryGetAccess( AccessRequest request); /** * Returns an {@link AccessToken} which has the requested rights and will * execute tasks after all conflicting {@code AccessToken}s have been * released. *

* This method returns immediately without waiting with an * {@code AccessToken} to which tasks can be scheduled to but these tasks * will not be executed until there are active conflicting * {@code AccessToken}s ({@code AccessToken}s not yet shutted down). * The returned result will also contain the conflicting * {@code AccessToken}s needed to be shutted down before tasks will be * executed by the returned {@code AccessToken}. *

* The following method will print the conflicting tokens and * schedule a task to be executed after the conflicting tokens were * released: *

{@code
     *  void executeTask(
     *     AccessManager manager,
     *     TaskExecutor executor,
     *     AccessRequest request
     *     CancelableTask task) {
     *   AccessResult result = manager.getScheduledAccess(request);
     *   try {
     *     System.out.println("Conflicts: " + result.getBlockingTokens());
     *     TaskExecutor tokenExecutor = result.getAccessToken().createExecutor(executor);
     *     tokenExecutor.execute(Cancellation.UNCANCELABLE_TOKEN, task);
     *   } finally {
     *     result.release();
     *   }
     * }
     * }
* * @param request the rights to be requested. This argument cannot be * {@code null}. * @return the {@code AccessToken} associated with the requested rights * and the list of tokens that must be shut down before a task * scheduled to the returned {@code AccessToken} can execute. This method * always returns a {@code non-null} {@code AccessToken}. * * @throws NullPointerException thrown if the request is {@code null} * * @see ScheduledAccessToken */ public AccessResult getScheduledAccess( AccessRequest request); }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy