1    /* --COPYRIGHT--,EPL
     2     *  Copyright (c) 2008 Texas Instruments and others.
     3     *  All rights reserved. This program and the accompanying materials
     4     *  are made available under the terms of the Eclipse Public License v1.0
     5     *  which accompanies this distribution, and is available at
     6     *  http://www.eclipse.org/legal/epl-v10.html
     7     * 
     8     *  Contributors:
     9     *      Texas Instruments - initial implementation
    10     * 
    11     * --/COPYRIGHT--*/
    12    
    13    /*!
    14     *  Callback notification on RTSC config parameters.
    15     *
    16     *  Lets user code receive a notification whenever a
    17     *  config param of a module or instance is read or modified.
    18     *
    19     *  @see ./doc-files/xdc/services/getset/package-summary.html JavaDoc
    20     */
    21    metaonly module GetSet
    22    {
    23        /*!
    24         *  ======== onGet ========
    25         *  Add a getter function to a field.
    26         *
    27         *  Each getter acts like an interrupt that is triggered by a read
    28         *  a field of an object. The field could be a config param of a module
    29         *  or an instance, or a field of a struct.
    30         *
    31         *  @a(example)
    32         *  The following example prints a message on any read of a
    33         *  config param named `cfg` in module `pkg.Mod`:
    34         *  @p(code)
    35         *    GetSet.onGet(Mod, "cfg", function(sel, val) {
    36         *        // prints "pkg.Mod.cfg returned <value>"
    37         *        print(this.$name + "." + sel + " returned " + val);
    38         *    });
    39         *  @p
    40         */
    41        function onGet(obj, sel, getter);
    42    
    43        /*!
    44         *  ======== onSet ========
    45         *  Add a setter function to a field.
    46         *
    47         *  Each setter acts like an interrupt that is triggered by modifying
    48         *  a field of an object. The field could be a config param of a module
    49         *  or an instance, or a field of a struct.
    50         *
    51         *  Setters execute only when the field actually changes value. They do
    52         *  not execute if the field's current value is written back to it.
    53         *
    54         *  Setters may themselves modify fields, and so trigger other setters.
    55         *  The original execution flow resumes when all fields stop changing
    56         *  value. In the case of cycles between setters, typically this means
    57         *  that at least one setter executes twice and makes no further
    58         *  changes the second time through.
    59         *
    60         *  If the setter throws a JavaScript Error or Java exception, then
    61         *  the field's original value is restored. The exception bubbles back
    62         *  through the call stack, so that if a setter caused a cascade of
    63         *  changes, all are restored to their original values.
    64         *
    65         *  @a(example)
    66         *  The following example prints a message on any write to a
    67         *  config param named `cfg` in module `pkg.Mod`:
    68         *  @p(code)
    69         *    GetSet.onSet(Mod, "cfg", function(sel, val, oldVal, exception) {
    70         *        // prints "pkg.Mod.cfg set to <value>"
    71         *        print(this.$name + "." + sel + " changed to " + val);
    72         *        // prints previous value before change
    73         *        print("  was " + oldVal);
    74         *    });
    75         *  @p
    76         *
    77         *  @a(example)
    78         *  The following example makes it an error to change `Mod.cfg`:
    79         *  @p(code)
    80         *    GetSet.onSet(Mod, "cfg", function(sel, val, oldVal, exception) {
    81         *        // don't throw an exception if already recovering from one
    82         *        if (!exception) {
    83         *            throw new Error("You'll never change me!");
    84         *        }
    85         *    });
    86         *  @p
    87         */
    88        function onSet(obj, sel, setter);
    89    
    90        /*!
    91         *  ======== createGroup ========
    92         *  Create a group of related setter functions.
    93         *
    94         *  The purpose of a group is to control interactions between setters.
    95         *  If each setter acts like an interrupt, then a group is like an
    96         *  interrupt controller that determines when setters are permitted
    97         *  to run.
    98         *
    99         *  Each group is non-reentrant. Once any setter in the group is
   100         *  running, it runs to completion before any other setter in the
   101         *  same group may run. This allows the setters to modify internal
   102         *  state without interference from other setters that operate on
   103         *  the same internal state.
   104         *
   105         *  Each group runs to completion. When a setter in the group runs, it
   106         *  might modify other config params and cause further setters in the
   107         *  same group to run. All of these complete before control is returned
   108         *  to the original execution flow. From the point of view of code
   109         *  outside the group, all the setters ran as an atomic operation.
   110         *
   111         *  Groups may be interrupted. When a setter modifies a config param
   112         *  that is being monitored by a second group, the second group starts
   113         *  running immediately. It will run to completion before returning
   114         *  control to the first group. So the first group sees the second
   115         *  group as atomic. This allows groups to be tested independently,
   116         *  and combined without affecting their behavior.
   117         *
   118         *  Cycles aren't permitted in the execution flow between groups. If a
   119         *  setter gets triggered from a group that has already been interrupted,
   120         *  it is deferred and run when control eventually returns to its own
   121         *  group. Cycles between groups can break the appearance of atomic
   122         *  execution, and so should be avoided when possible.
   123         *
   124         *  @a(returns)
   125         *  A Java object of class
   126         *    {@link ./doc-files/xdc/services/getset/Group.html Group}.
   127         *  Can then use Group.onSet() to add functions to the group.
   128         *
   129         *  @a(example)
   130         *  The following example code forces the values of the config params
   131         *  `ModA.a` and `ModB.b` to be equal:
   132         *  @p(code)
   133         *    var group = GetSet.createGroup();
   134         *    group.onSet(ModA, "a", function aToB(){ ModB.b = ModA.a; });
   135         *    group.onSet(ModB, "b", function bToA(){ ModA.a = ModB.b; });
   136         *  @p
   137         */
   138        function createGroup();
   139    
   140        /*!
   141         *  ======== init ========
   142         *  Add support for getters and setters to all fields of an object.
   143         *
   144         *  Initializes getter and setter support for every field of
   145         *  the object. The object can be a module, instance, or structure.
   146         *
   147         *  This is a convenience function. The `onSet` and `onGet` functions
   148         *  already add support to the one field of interest. The `init`
   149         *  function is useful mostly to make fields visible to global setters
   150         *  and getters, for example for debugging.
   151         */
   152        function init(obj);
   153    
   154        /*!
   155         *  ======== debug ========
   156         *  Print execution trace info showing the flow of getters and setters.
   157         */
   158        config Bool debug = false;
   159    
   160        /*!
   161         *  ======== maxIterations ========
   162         *  Limit the number of iterations allowed for a group to converge, to
   163         *  help debug. The default value of 0 means no limit.
   164         */
   165        config int maxIterations = 0;
   166    
   167        /*!
   168         *  ======== maxStackDepth ========
   169         *  Set the maximum allowed depth of recursively nested setters, as
   170         *  a debugging aid. The default value of 0 means no limit.
   171         */
   172        config int maxStackDepth = 0;
   173    }