Package abstrasy

Source Code of abstrasy.AtomicLock

package abstrasy;

/**
* Abstrasy Interpreter
*
* Copyright : Copyright (c) 2006-2012, Luc Bruninx.
*
* Concédée sous licence EUPL, version 1.1 uniquement (la «Licence»).
*
* Vous ne pouvez utiliser la présente oeuvre que conformément à la Licence.
* Vous pouvez obtenir une copie de la Licence à l’adresse suivante:
*
*   http://www.osor.eu/eupl
*
* Sauf obligation légale ou contractuelle écrite, le logiciel distribué sous
* la Licence est distribué "en l’état", SANS GARANTIES OU CONDITIONS QUELLES
* QU’ELLES SOIENT, expresses ou implicites.
*
* Consultez la Licence pour les autorisations et les restrictions
* linguistiques spécifiques relevant de la Licence.
*
*
* @author Luc Bruninx
* @version 1.0
*/

import abstrasy.interpreter.InterpreterException;
import abstrasy.interpreter.StdErrors;

class AtomicLock {

    /*
     * Gestion du réentrant (dans la section critique - donc en ayant déjà le verrou)
     */
    private int reentrant = 0;

    /*
     * Attention!!, volatile nécessaire...
     */
    volatile private Interpreter lock = null;

    private synchronized boolean tryReentrant_cas_(Interpreter expected) {
        if(lock==expected){
            reentrant++;
            return true;
        }
        else
            return false;
    }

    synchronized void extractReentrantOf(AtomicLock other) {
        synchronized (other) {
            reentrant += other.reentrant;
            other.reentrant = 0;
        }
    }

    synchronized boolean isExclusive() {
        return lock == Interpreter.SHARED_INTERPRETER ? false: true;
    }

    private synchronized Interpreter getAndSet(Interpreter lock) {
        Interpreter old = this.lock;
        this.lock = lock;
        return old;
    }

    Interpreter get() {
        return lock;
    }

    private synchronized boolean tryLock_cas_(Interpreter newlock,Node node) {
        if (lock == null) {
            lock = newlock;
            if(reentrant++ == 0)newlock.threadlock_A_add(node);
            return false;
        }
        else {
            return true;
        }
    }

    /**
     * Tentative d'obtenir un verrou dans une boucle d'attente passive.
     * Cette méthode est basée sur le principe du compare-and-set (voir
     * méthode private tryLock_cas_(Interpreter newlock,Node node) ci-desus).
     *
     * Le verrou ne peut être obtenu que s'il est libre.
     *
     * Si ce n'est pas le cas, la méthode retourne true (ce qui est plus facile
     * pour une implémentation dans une boucle while(tryLock){wait}...
     *
     * @param newlock
     * @param node
     * @return
     */
    boolean tryLock(Interpreter newlock, Node node){
        return tryLock_cas_(newlock,node)
    }
   
   
    /**
     * Acquisition d'un verroux via une attente active.
     *
     * Est utilisé par (sync v {...}) et (share v {...}):
     *
     *   - sync demande un verrou exclusif:
     *     ---------------------------------
     *        Cela signifie qu'une exception doit être déclenchée si un autre processus essaye d'accéder
     *        à la données sans demander de verrou au préalable.
     *
     *   - share demande un verrou non exclusif:
     *     ------------------------------------
     *        Ce la signifie qu'aucune exception ne sera déclenchée si on accède à la donnée (pour la consulter)
     *        sans avoir demandé de verrou au préalable.
     *
     *
     * S'arrête en cas d'exception ou de threadRaising.
     *
     * @param interpreter qui demande le verrou
     * @param node à verrouiller
     * @throws Exception
     */
    void acquirelock(Interpreter interpreter,Node node) throws Exception {
        //
        // si on a déjà le verrou, on incrémente simplement le réentrant
        //
      
        if(tryReentrant_cas_(interpreter))
            return;
       
       
        //
        // on a pas le verrou...
        //
        // on va donc le chercher activement...
        //
        boolean unraising = true;
        Exception exc = null;
        interpreter.threadlock_R_add(node);
        try {
            while (tryLock_cas_(interpreter,node)) {
                interpreter.thowsDeadlock(lock);
                unraising = !interpreter.isThreadRaising();
            }
        }
        catch (InterpreterException e) {
            exc = e;
        }
        interpreter.threadlock_R_remove(node);
        if (exc != null)
            throw exc;
        return;
    }
   
    /**
     * Déverrouillage du node sans attente passive.
     *
     * Est utilisé pas atomic et lock. Toutefois, c'est cette méthoque que
     * l'opérateur atomic appelle directement à la fin de la section (atomic n {...})
     *
     */
    synchronized void unlock(Interpreter interpreter,Node node) throws InterpreterException {
        // normalement, je suis tout seul à travailler sur ce node...
        // si le compteur réentrant est 0, alors...
        --reentrant;
        if (reentrant == 0){
           
            Interpreter r=getAndSet(null);
            interpreter.threadlock_A_remove(node);
   
            if (r != interpreter){ // on libère le verrou...
                //System.out.println(r);
                //System.out.println(interpreter);
                //System.out.println(Interpreter.SHARED_INTERPRETER);
                throw new InterpreterException(StdErrors.extend(StdErrors.Internal_error, "Node already unlocked"));
            }
           
        }
        else if(reentrant<0){
            throw new InterpreterException(StdErrors.extend(StdErrors.Internal_error, "Negative reentrant"));
        }
    }


    /**
     * Le node est-il verrouillé par mon acteur (moi-même).
     *
     * @param interpreter
     * @return
     */
    boolean isLockedBy(Interpreter interpreter) {
        return lock == interpreter; // attention!!! est-ce verrouillé par l'interpréter fourni en argument !!!
    }
}

TOP

Related Classes of abstrasy.AtomicLock

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.