# CriticalSectionManager.java

    /*
    ** Module   : CriticalSectionManager.java
    ** Abstract : provides a protection mechanism for critical sections which are
    **            sensitive to thread interruption.
    **
    ** Copyright (c) 2009-2017, Golden Code Development Corporation.
    **
    ** -#- -I- --Date-- --JPRM-- -------------------Description-------------------
    ** 001 CA  20091106   @44322 Initial version. Provides a protection mechanism
    **                           for critical sections sensitive to thread
    **                           interruption.
    ** 002 CA  20091203   @44475 Fixed a bug in beginSection - we must ensure the
    **                           thread interrupted flag is cleared, regardless of
    **                           the value of wa.threadInterrupted field; else,
    **                           problems may appear if nested crticial sections
    **                           are used.
    */
    /*
    ** This program is free software: you can redistribute it and/or modify
    ** it under the terms of the GNU Affero General Public License as
    ** published by the Free Software Foundation, either version 3 of the
    ** License, or (at your option) any later version.
    **
    ** This program is distributed in the hope that it will be useful,
    ** but WITHOUT ANY WARRANTY; without even the implied warranty of
    ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    ** GNU Affero General Public License for more details.
    **
    ** You may find a copy of the GNU Affero GPL version 3 at the following
    ** location: https://www.gnu.org/licenses/agpl-3.0.en.html
    **
    ** Additional terms under GNU Affero GPL version 3 section 7:
    **
    **   Under Section 7 of the GNU Affero GPL version 3, the following additional
    **   terms apply to the works covered under the License.  These additional terms
    **   are non-permissive additional terms allowed under Section 7 of the GNU
    **   Affero GPL version 3 and may not be removed by you.
    **
    **   0. Attribution Requirement.
    **
    **     You must preserve all legal notices or author attributions in the covered
    **     work or Appropriate Legal Notices displayed by works containing the covered
    **     work.  You may not remove from the covered work any author or developer
    **     credit already included within the covered work.
    **
    **   1. No License To Use Trademarks.
    **
    **     This license does not grant any license or rights to use the trademarks
    **     Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
    **     of Golden Code Development Corporation. You are not authorized to use the
    **     name Golden Code, FWD, or the names of any author or contributor, for
    **     publicity purposes without written authorization.
    **
    **   2. No Misrepresentation of Affiliation.
    **
    **     You may not represent yourself as Golden Code Development Corporation or FWD.
    **
    **     You may not represent yourself for publicity purposes as associated with
    **     Golden Code Development Corporation, FWD, or any author or contributor to
    **     the covered work, without written authorization.
    **
    **   3. No Misrepresentation of Source or Origin.
    **
    **     You may not represent the covered work as solely your work.  All modified
    **     versions of the covered work must be marked in a reasonable way to make it
    **     clear that the modified work is not originating from Golden Code Development
    **     Corporation or FWD.  All modified versions must contain the notices of
    **     attribution required in this license.
    */

    package com.goldencode.p2j.net;

    import com.goldencode.p2j.security.ContextLocal;

    /**
     * This class provides a mechanism to protect critical sections against thread
     * interruption. By critical sections we mean any portion of code which is
     * sensitive to thread interruption (i.e. would fail if it sees the thread
     * marked as interrupted), but that portion of code must complete regardless
     * of the thread interrupt state.
     * <p>
     * The class provides these methods:
     * <ol>
     *    <li> {@link #beginSection()} and {@link #endSection()} must bracket any
     *         portion of code which is determined to be sensitive to thread
     *         interruption. Also, the {@link #endSection()} method ensures that,
     *         when the critical section ends, it will force the interrupt flag
     *         of the thread to be set if it was set when the critical section
     *         started OR if an interruption occurred during the critical section
     *         (which was deferred).
     *    </li>
     *    <li> {@link #interrupt} is used to deliver an interruption to the
     *         Conversation thread. This ensures that the interrupt will never bes
     *         executed while a critical section is in process (in such a case the
     *         interrupt is remembered but its application is deferred until the
     *         {@link #endSection} finds that all nested critical sections have
     *         been exited).  If no critical section is in process, the interrupt
     *         is immediately applied to the given thread.
     *    </li>
     * </ol>
     */
    public final class CriticalSectionManager
    {
       /** Store context-local state variables. */
       private static final ContextLocal<WorkArea> instance =
          new ContextLocal<WorkArea>()
          {
             protected WorkArea initialValue()
             {
                return (new WorkArea());
             }
          };

       /**
        * Private constructor. Doesn't allow instances of this class.
        */
       private CriticalSectionManager()
       {
          // do not allow instantiation of this class
       }

       /**
        * Method called before the start of a critical section. The method waits
        * for any lock to be released, to not interfere with thread interruption.
        * <p>
        * When the lock was released, it will mark the start of a new critical
        * section and also save the the interrupted state of the current thread.
        */
       public static void beginSection()
       {
          WorkArea wa = instance.get();

          synchronized (wa)
          {
             // start the critical section
             wa.criticalSection++;

             // clear and save the interrupted state
             boolean interrupt = Thread.interrupted();
             wa.threadInterrupted = wa.threadInterrupted || interrupt;
          }
       }

       /**
        * Method called right after the end of a critical section; must be
        * executed in a <code>finally</code> block.
        * <p>
        * This will decrement the critical section count and it will force the
        * interrupt flag of the thread to be set if it was set when the critical
        * section started OR if an interruption occurred during the critical
        * section (if there is a deferred interrupt needing to be delivered).
        */
       public static void endSection()
       {
          WorkArea wa = instance.get();

          synchronized (wa)
          {
             wa.criticalSection--;

             if (wa.criticalSection == 0)
             {
                if (wa.threadInterrupted)
                {
                   // if required and last critical section ended, interrupt
                   // the thread
                   Thread.currentThread().interrupt();
                }

                // all critical sections finished, reset the flag
                wa.threadInterrupted = false;
             }
          }
       }

       /**
        * Notify the target thread about an interruption. If a critical section is
        * in progress, postpone the interrupt until it is finished.
        *
        * @param   thread
        *          The target thread which should be interrupted.
        */
       public static void interrupt(Thread thread)
       {
          WorkArea wa = instance.get();

          synchronized (wa)
          {
             if (wa.criticalSection == 0)
             {
                thread.interrupt();
             }
             else
             {
                wa.threadInterrupted = true;
             }
          }
       }

       /**
        * Container for context-local variables.
        */
       private static final class WorkArea
       {
          /** Count of critical section being executed. */
          private int criticalSection = 0;

          /** Thread interruption state flag. */
          private boolean threadInterrupted = false;
       }
    }