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) {
    70         *        // prints "pkg.Mod.cfg set to <value>"
    71         *        print(this.$name + "." + sel + " set to " + val);
    72         *    });
    73         *  @p
    74         *
    75         *  @a(example)
    76         *  The following example makes it an error to change `Mod.cfg`:
    77         *  @p(code)
    78         *    GetSet.onSet(Mod, "cfg", function(sel, val) {
    79         *        throw new Error("You'll never change me!");
    80         *    });
    81         *  @p
    82         */
    83        function onSet(obj, sel, setter);
    84    
    85        /*!
    86         *  ======== createGroup ========
    87         *  Create a group of related setter functions.
    88         *
    89         *  The purpose of a group is to control interactions between setters.
    90         *  If each setter acts like an interrupt, then a group is like an
    91         *  interrupt controller that determines when setters are permitted
    92         *  to run.
    93         *
    94         *  Each group is non-reentrant. Once any setter in the group is
    95         *  running, it runs to completion before any other setter in the
    96         *  same group may run. This allows the setters to modify internal
    97         *  state without interference from other setters that operate on
    98         *  the same internal state.
    99         *
   100         *  Each group runs to completion. When a setter in the group runs, it
   101         *  might modify other config params and cause further setters in the
   102         *  same group to run. All of these complete before control is returned
   103         *  to the original execution flow. From the point of view of code
   104         *  outside the group, all the setters ran as an atomic operation.
   105         *
   106         *  Groups may be interrupted. When a setter modifies a config param
   107         *  that is being monitored by a second group, the second group starts
   108         *  running immediately. It will run to completion before returning
   109         *  control to the first group. So the first group sees the second
   110         *  group as atomic. This allows groups to be tested independently,
   111         *  and combined without affecting their behavior.
   112         *
   113         *  Cycles aren't permitted in the execution flow between groups. If a
   114         *  setter gets triggered from a group that has already been interrupted,
   115         *  it is deferred and run when control eventually returns to its own
   116         *  group. Cycles between groups can break the appearance of atomic
   117         *  execution, and so should be avoided when possible.
   118         *
   119         *  @a(returns)
   120         *  A Java object of class
   121         *    {@link ./doc-files/xdc/services/getset/Group.html Group}.
   122         *  Can then use Group.onSet() to add functions to the group.
   123         *
   124         *  @a(example)
   125         *  The following example code forces the values of the config params
   126         *  `ModA.a` and `ModB.b` to be equal:
   127         *  @p(code)
   128         *    var group = GetSet.createGroup();
   129         *    group.onSet(ModA, "a", function aToB(){ ModB.b = ModA.a; });
   130         *    group.onSet(ModB, "b", function bToA(){ ModA.a = ModB.b; });
   131         *  @p
   132         */
   133        function createGroup();
   134    
   135        /*!
   136         *  ======== init ========
   137         *  Add support for getters and setters to all fields of an object.
   138         *
   139         *  Initializes getter and setter support for every field of
   140         *  the object. The object can be a module, instance, or structure.
   141         *
   142         *  This is a convenience function. The `onSet` and `onGet` functions
   143         *  already add support to the one field of interest. The `init`
   144         *  function is useful mostly to make fields visible to global setters
   145         *  and getters, for example for debugging.
   146         */
   147        function init(obj);
   148    
   149        /*!
   150         *  ======== debug ========
   151         *  Print execution trace info showing the flow of getters and setters.
   152         */
   153        config Bool debug = false;
   154    
   155        /*!
   156         *  ======== maxIterations ========
   157         *  Limit the number of iterations allowed for a group to converge, to
   158         *  help debug. The default value of 0 means no limit.
   159         */
   160        config int maxIterations = 0;
   161    
   162        /*!
   163         *  ======== maxStackDepth ========
   164         *  Set the maximum allowed depth of recursively nested setters, as
   165         *  a debugging aid. The default value of 0 means no limit.
   166         */
   167        config int maxStackDepth = 0;
   168    }