SetString (Subsystem function): Difference between revisions

From m204wiki
Jump to navigation Jump to search
m (1 revision)
(Automatically generated page update)
 
(5 intermediate revisions by one other user not shown)
Line 1: Line 1:
{{Template:Subsystem:SetString subtitle}}
{{Template:Subsystem:SetString subtitle}}
The <var>SetString</var> shared [[Notation conventions for methods#Callable functions|callable]] function sets a <var>[[Subsystem_class|Subsystem]]</var> string.
The <var>SetString</var> shared [[Notation conventions for methods#Callable functions|callable]] function sets a [[Subsystem_class#System_and_subsystem_globals_and_strings|subsystem string]].


==Syntax==
==Syntax==
{{Template:Subsystem:SetString syntax}}
{{Template:Subsystem:SetString syntax}}
===Syntax terms===
===Syntax terms===
<table class="syntaxTable">
<table class="syntaxTable">
<tr><th>%number</th><td>A numeric result that indicates whether the string update succeeded.  <var class="term">%number</var> is set to 1 upon success. If <var class="term">oldValue</var> is specified and does not match the current setting of the string, the update is not performed and a 0 is returned.</td></tr>
<tr><th>%number</th><td>A numeric result that indicates whether the string update succeeded.  <var class="term">%number</var> is set to 1 upon success. If <var class="term">oldValue</var> is specified and does not match the current setting of the string, the update is not performed and a 0 is returned.</td></tr>
<tr><th><var>%(Subsystem)</var></th>
 
<tr><th><var class="nobr">%(Subsystem)</var></th>
<td>The class name in parentheses denotes a [[Notation conventions for methods#Shared methods|shared]] method. <var>SetString</var> can also be invoked via a <var>Subsystem</var> object variable, which may be <var>null</var>.</td></tr>
<td>The class name in parentheses denotes a [[Notation conventions for methods#Shared methods|shared]] method. <var>SetString</var> can also be invoked via a <var>Subsystem</var> object variable, which may be <var>null</var>.</td></tr>
<tr><th>name</th>
<tr><th>name</th>
<td>A string that identifies the global string to be set.</td></tr>
<td>A string that identifies the global string to be set.</td></tr>
<tr><th>value</th>
<tr><th>value</th>
<td>A string that identifies the new value for the global string.</td></tr>
<td>A string that identifies the new value for the global string.</td></tr>
<tr><th>oldValue</th>
<tr><th>oldValue</th>
<td>A string that identifies a value to be compared against the current value of the <var>Subsystem</var> string before doing the update. This is an optional argument.</td></tr>
<td>A string that identifies a value to be compared against the current value of the <var>Subsystem</var> string before doing the update. This is an optional argument.</td></tr>
Line 19: Line 24:


==Usage notes==
==Usage notes==
<ul><li>All errors result in request cancellation.
<ul>
<li>All errors result in request cancellation.
 
<li>It is not an error to set a string that is not set.
<li>It is not an error to set a string that is not set.
<li><var>SetString</var> sets the string for the current subsystem context, which is indicated by the <var>[[Context_(Subsystem_property)|Context]]</var> property.
<li><var>SetString</var> sets the string for the current subsystem context, which is indicated by the <var>[[Context_(Subsystem_property)|Context]]</var> property.
<li>Unlike <var>[[SetGlobal_(Subsystem_subroutine)#Usage_notes|SetGlobal]]</var>, <var>SetString</var> does not turn off multiprocessing, and it is designed for fairly high levels of updating.
<li>Unlike <var>[[SetGlobal_(Subsystem_subroutine)#Usage_notes|SetGlobal]]</var>, <var>SetString</var> does not turn off multiprocessing, and it is designed for fairly high levels of updating.
</ul>
</ul>


==Examples==
==Examples==
<ol><li>The following statement sets the system string called DIAMONDS:
<ol>
<p class="code">%(system):setString('DIAMONDS', 'CLEAR')</p>
<li>The following statement sets the subsystem string called <code>DIAMONDS</code>:
<li>The <var class="term">oldValue</var> argument makes it possible to use <var>System</var> strings as structures that can be safely updated by multiple users. For example, one might want to maintain a system-wide counter. This can be accomplished as follows:
<p class="code">%(subSystem):setString('DIAMONDS', 'CLEAR')</p>
 
<li>The <var class="term">oldValue</var> argument makes it possible to use <var>Subsystem</var> strings as structures that can be safely updated by multiple users. For example, one might want to maintain a subsystem-wide counter. This can be accomplished as follows:
<p class="code">%value is longString
<p class="code">%value is longString
%newValue is float
%newValue is float


%value = %(system):string('Counter')
%value = %(subsystem):string('Counter')
%newValue = %value + 1
%newValue = %value + 1
%(system):setString('Counter', %newValue)
%(subsystem):setString('Counter', %newValue)
</p>
</p>
Unfortunately, another thread might update the value of the counter between the time the above code retrieves the value (with <var>[[String (Subsystem function)|String]]</var>) and the time it updates it (with <var>SetString</var>).  In such a case, an increment of the counter might be missed. This is more likely, of course, in an <var class="product">MP/204</var> environment, but you should not count on it being impossible in a non-<var class="product">MP/204</var> environment. To safely update a counter, you can do the following:
Unfortunately, another thread might update the value of the counter between the time the above code retrieves the value (with <var>[[String (Subsystem function)|String]]</var>) and the time it updates it (with <var>SetString</var>).  In such a case, an increment of the counter might be missed. This is more likely, of course, in an <var class="product">MP/204</var> environment, but you should not count on it being impossible in a non-<var class="product">MP/204</var> environment. To safely update a counter, you can do the following:
<p class="code">%value is longString
<p class="code">%value is longString
%newValue is float
%newValue is float
Line 42: Line 53:


repeat while not %success
repeat while not %success
   %value = %(system):string('Counter')
   %value = %(subsystem):string('Counter')
   %newValue = %value + 1
   %newValue = %value + 1
   %success = %(system):setString('Counter', %newValue, -
   %success = %(subsystem):setString('Counter', %newValue, %value)
                                            %value)
end repeat
end repeat
</p>
</p>
If no user has updated Counter between the <var>String</var> and the <var>SetString</var> methods, the update would succeed. If some other user has updated it, the update would not be performed, <var>SetString</var> would return a 0, and the repeat loop would be repeated.
If no user has updated <code>Counter</code> between the <var>String</var> and the <var>SetString</var> methods, the update would succeed. If some other user has updated it, the update would not be performed, <var>SetString</var> would return a 0, and the repeat loop would be repeated.
<p>While this looks nasty &amp;amp;#x2014; it seems the code could loop forever &amp;amp;#x2014; it's not that bad. Since the only thing that causes the <var>SetString</var> to fail is another user updating the same string at the same time; even if a hundred users were in this loop, at least one of them would succeed on each iteration. So unless the subsystem is doing almost nothing else, all the updates would be performed in fairly short order.</p>
<p>
<li>This technique can be used with considerably more complex data-structures. For example, one can actually store a serialized <var>[[XmlDoc_API#The_XmlDoc_class|XmlDoc]]</var> in a <var>subsystem</var> string. A request can retrieve the current structure, manipulate it, and then replace the updated structure:
While this looks nasty &mdash; it seems the code could loop forever &mdash; it's not that bad. Since the only thing that causes the <var>SetString</var> to fail is another user updating the same string at the same time; even if a hundred users were in this loop, at least one of them would succeed on each iteration. So unless the subsystem is doing almost nothing else, all the updates would be performed in fairly short order.</p>
 
<li>This technique can be used with considerably more complex data-structures. For example, one can actually store a serialized <var>[[XmlDoc_API#The_XmlDoc_class|XmlDoc]]</var> in a subsystem string. A request can retrieve the current structure, manipulate it, and then replace the updated structure:
<p class="code">%value is longString
<p class="code">%value is longString
%newValue is longString
%newValue is longString
Line 57: Line 69:


repeat while not %success
repeat while not %success
   %value = %(system):string('Complicated')
   %value = %(subsystem):string('Complicated')
   %myDoc = new
   %myDoc = new
   %myDoc:loadXml(%value)
   %myDoc:loadXml(%value)
     ... manipulate myDoc
     ... manipulate myDoc
   %newValue = %myDoc:serial(,'EBCDIC')
   %newValue = %myDoc:serial(,'EBCDIC')
   %success = %(system):setString('Complicated', -
   %success = %(subsystem):setString('Complicated', %newValue, %value)
                                  %newValue, %value)
end repeat
end repeat
</p>
</p>
Note that the above code assumes that the <code>Complicated</code> subsystem string is already set. If the application cannot guarantee that <code>Complicated</code> has been set, there should be a test for the null string, bypassing the <var>[[LoadXml_(XmlDoc/XmlNode_function)|loadXml]]</var> operation and instead populating the <var>XmlDoc</var> with some initial nodes.
Note that the above code assumes that the <code>Complicated</code> subsystem string is already set. If the application cannot guarantee that <code>Complicated</code> has been set, there should be a test for the null string, bypassing the <var>[[LoadXml_(XmlDoc/XmlNode_function)|loadXml]]</var> operation and instead populating the <var>XmlDoc</var> with some initial nodes.
<p>The document is stored in the subsystem string in EBCDIC. This is not necessary &amp;amp;#x2014; the document could be stored in UTF-8 encoding &amp;amp;#x2014; it is just easier to debug this code if it is saved in EBCDIC.</p>
<p>
The document is stored in the subsystem string in EBCDIC. This is not necessary &mdash; the document could be stored in UTF-8 encoding &mdash; it is just easier to debug this code if it is saved in EBCDIC.</p>
</ol>
</ol>


==See also==
==See also==
{{Template:Subsystem:SetString footer}}
{{Template:Subsystem:SetString footer}}

Latest revision as of 00:31, 16 February 2014

Set a subsystem string (Subsystem class)

The SetString shared callable function sets a subsystem string.

Syntax

[%number =] %(Subsystem):SetString( name, value, [oldValue])

Syntax terms

%numberA numeric result that indicates whether the string update succeeded. %number is set to 1 upon success. If oldValue is specified and does not match the current setting of the string, the update is not performed and a 0 is returned.
%(Subsystem) The class name in parentheses denotes a shared method. SetString can also be invoked via a Subsystem object variable, which may be null.
name A string that identifies the global string to be set.
value A string that identifies the new value for the global string.
oldValue A string that identifies a value to be compared against the current value of the Subsystem string before doing the update. This is an optional argument.


Usage notes

  • All errors result in request cancellation.
  • It is not an error to set a string that is not set.
  • SetString sets the string for the current subsystem context, which is indicated by the Context property.
  • Unlike SetGlobal, SetString does not turn off multiprocessing, and it is designed for fairly high levels of updating.

Examples

  1. The following statement sets the subsystem string called DIAMONDS:

    %(subSystem):setString('DIAMONDS', 'CLEAR')

  2. The oldValue argument makes it possible to use Subsystem strings as structures that can be safely updated by multiple users. For example, one might want to maintain a subsystem-wide counter. This can be accomplished as follows:

    %value is longString %newValue is float %value = %(subsystem):string('Counter') %newValue = %value + 1 %(subsystem):setString('Counter', %newValue)

    Unfortunately, another thread might update the value of the counter between the time the above code retrieves the value (with String) and the time it updates it (with SetString). In such a case, an increment of the counter might be missed. This is more likely, of course, in an MP/204 environment, but you should not count on it being impossible in a non-MP/204 environment. To safely update a counter, you can do the following:

    %value is longString %newValue is float %success is float repeat while not %success %value = %(subsystem):string('Counter') %newValue = %value + 1 %success = %(subsystem):setString('Counter', %newValue, %value) end repeat

    If no user has updated Counter between the String and the SetString methods, the update would succeed. If some other user has updated it, the update would not be performed, SetString would return a 0, and the repeat loop would be repeated.

    While this looks nasty — it seems the code could loop forever — it's not that bad. Since the only thing that causes the SetString to fail is another user updating the same string at the same time; even if a hundred users were in this loop, at least one of them would succeed on each iteration. So unless the subsystem is doing almost nothing else, all the updates would be performed in fairly short order.

  3. This technique can be used with considerably more complex data-structures. For example, one can actually store a serialized XmlDoc in a subsystem string. A request can retrieve the current structure, manipulate it, and then replace the updated structure:

    %value is longString %newValue is longString %myDoc is object xmlDoc %success is float repeat while not %success %value = %(subsystem):string('Complicated') %myDoc = new %myDoc:loadXml(%value) ... manipulate myDoc %newValue = %myDoc:serial(,'EBCDIC') %success = %(subsystem):setString('Complicated', %newValue, %value) end repeat

    Note that the above code assumes that the Complicated subsystem string is already set. If the application cannot guarantee that Complicated has been set, there should be a test for the null string, bypassing the loadXml operation and instead populating the XmlDoc with some initial nodes.

    The document is stored in the subsystem string in EBCDIC. This is not necessary — the document could be stored in UTF-8 encoding — it is just easier to debug this code if it is saved in EBCDIC.

See also