-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBlogGlobals.html
308 lines (299 loc) · 16.7 KB
/
BlogGlobals.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
<!DOCTYPE html>
<html>
<!--
BlogGlobals.html
-->
<head>
<title>Blog Globals</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<!-- <link rel="icon" type="image/x-icon" href="./images/favicon.ico" /> -->
<link rel="stylesheet" href="css/StylesPhoto.css" />
<link rel="stylesheet" href="css/StylesSizerComp.css" />
<!-- PageFrame infrastructure -->
<link rel="stylesheet" href="css/StylesPageFrameDefaults.css" />
<link rel="stylesheet" href="css/StylesPageFrameStructure.css" />
<link rel="stylesheet" href="css/StylesPageFrameMenus.css" />
<link rel="stylesheet" href="css/StylesPageFrameThemePython.css" />
<link rel="stylesheet" href="css/StylesWebComponents.css" />
<script src="js/ScriptsWebComponents.js"></script>
<!--<script src="js/ScriptsPageFrameDefaults.js"></script>-->
<script src="js/ScriptsPageFramePosts.js"></script>
<script src="js/ScriptsPageFramePagesPosts.js"></script>
<script src="js/ScriptsPageFrameKeyboard.js"></script>
<!-- No need for Pages script for pages with no next or prev pages -->
<!--<script src="js/ScriptsPageFramePages.js"></script>-->
<!-- <script src="js/ScriptsTemplate.js"></script>
<link rel="stylesheet" href="css/StylesTemplate.css" /> -->
<style>
h3 {
margin-top: 1.5em;
}
#subtitle {
margin-top: 0.4em;
margin-bottom: 0.3em;
}
#github header summary {
border: 1px solid var(--light);
}
#github summary {
padding-right: 2em;
}
/* #github .menuHead {
margin:0em -0.25em 0.0em -0.25em;
padding:0.25em 0.5em;
} */
</style>
<script>
function load() {
initialize();
//loadif();
}
</script>
<style>
#github note {
display: block;
width:max-content;
border:1px solid red;
padding:0.5em 1.0em;
margin:0.5em 0em;
}
#github .bargraph {
border: 1px solid var(--dark);
/* background-color: #bbb; */
padding: 0.1em 0.5em;
font-size:0.9em;
}
#github table {
border:2px solid var(--dark);
}
#github table td {
padding:0.25em 1.0em;
border:none;
}
body {
user-select:none;
}
</style>
<script>
function clickstat() {
// prevent parent click event handling
event.stopImmediatePropagation();
}
</script>
</head>
<body id="github" onload="load()" style="position:relative;">
<a id="Next" href="BlogOCD.html">Next</a>
<a id="Prev" href="BlogObjectModels.html">Prev</a>
<page-frame>
<frame-header>
<nav id="navbar"></nav>
</frame-header>
<main id="main">
<div id="about" onclick="this.style.display = 'none'">about</div>
<div id="page">Blog: Globals</div>
<div id="modified">11/26/2024</div>
<div id="hlp"></div>
<a id="top"></a>
<content style="height:100vh; position:relative;">
<header style="cursor:pointer;" onclick="loadif()">
<!-- <a target="_blank" class="repoLink" href="https://github.com/JimFawcett">github Repositories</a> -->
<hgroup id="pagetitle" style="border: 2px solid var(--dark);">
<h1 id="title">Blog: Globals</h1>
<h3 class="indent" id="subtitle">
scopes and dependencies
</h3>
</hgroup>
<!-- <img style="width:100%; margin:-0.1em 0em; border:2px solid var(--dark); padding:0.5em; background-color:var(--light);" src="Pictures/officestrip3a.svg" /> -->
<div class="darkItem" onclick="loadif()" style="cursor:pointer; position:relative; padding:0.0em 0em 0.25em 0em; margin-top:-0.50em; border:2px solid var(--dark);">
<a class="repoLinks" target="_blank" href="https://github.com/JimFawcett" style="color:var(--atten); margin-left:1.5em;">About</a>
<div style="font-size:0.9em; position:absolute; top:0.1em; right:1.5em;">click to toggle Site Explorer</div>
<div style="height:0.5em;"></div>
</div>
</header>
<div style="height:1.5em;"></div>
<h3>Initial Thoughts:</h3>
<t-b>
Global data is often said to be <a href="http://c2.com/cgi/wiki?GlobalVariablesAreBad">"bad"</a>. By global, we mean that the data is subject
to some form of non-local sharing. Throughout this discussion we take "data" to mean an instance of some language or user defined type, including language
primitives like ints.
<t-b>
</t-b>
Most data is shared, otherwise why create it in the first place? However, the scope of this sharing has deep
implications for the ease and effectiveness of the code's implementation and maintenance.
<t-b>
</t-b>
<h3 id="globals">Problems with Global Sharing:</h3>
<ul class="indent">
<li>
Access to a datum from widely separated parts of a program's code makes it difficult to understand its use and evaluate correctness of the code's operations.
</li>
<li>
If the data isn't wrapped in a class or struct it isn't possible to control or monitor access to the data's values.
</li>
<li>
Access to a specific data item in many parts of the code bind all of those regions to the definition of the data. So any changes of that definition will affect
all of the clients of the data and may require massive editing and recompilation when changes happen. Thus, the code becomes brittle and easily
broken by change.
</li>
<li>
All accesses to a specific datum by multiple threads must be synchronized with locks to avoid race conditions in the program's behavior. If the data type
is thread safe, like a well designed blocking queue, that may not be an issue, but for primitive and non-thread safe types, global access makes
threading models very complex, difficult to reason about, and very hard to make correct.
</li>
<li>
A global datum may be used by two developers working on code for the same process in different and conflicting ways, one interrupting the data storage activities
of the other.
<div style="height:0.75em;">
If there are multiple writers and readers of a global datum one writer's value may be overwritten by another writer before being read. This may or may
not result in problematic behavior, but if it does it will often be very difficult to find and rectify.
</li>
</ul>
<t-b>
These problems make development, testing, and maintenance of code containing global sharing difficult and often quite unproductive.
</t-b>
<div style="width:calc(100vw - 9rem);">
<div style="float:right">
<img src="Pictures/placement.jpg" width="700" />
</div>
</div>
<h3 id="scopes">Scopes:</h3>
<t-b>
For purposes of this discussion we will define a package as a single source code file in C# and Java, and, for C and C++, a pair of source code files - header and matching implementation.
</t-b>
<t-b>
Access to data in the four major development languages C, C++, Java, and C#, depends on scope. These languages define, for each package, a tree of nested scopes
using the symbols "{" and "}". Code that resides outside any "{", "}" block is said to be in the program's
global scope. There are two kinds of scope:
<ul class="indent">
<li>
Namespace, class, struct, and enum scopes are compile-time artifacts. They are syntatical constructs that serve to associate function and type declarations
and access specifiers with a class or struct and associate named constants with an enum. They play no role at run-time.
</li>
<li>
Function and control scopes have affects at both compile-time and run-time. As the thread of execution enters one of these scopes
memory is allocated on the program's stack to hold its calling parameters, local data, and return values. This memory is allocated to a
specific scope only for execution and is de-allocated when execution leaves that scope, to be reused for subsequent scope activations.
We call this memory a stack frame and normally think of it as lying at the end of a sequence of adjacent frames belonging to its parent
scopes, in activation order.
</li>
</ul>
Namespaces can be defined only at the global level. That is, they may be sequenced and nested in the global scope, but may not be nested within any
non-namespace scope. They serve to qualify program names to avoid conflicts when code is developed by more than one person, and also to provide a
weak semantic structuring for large bodies of code.
</t-b>
<t-b>
In C# and Java, handles to reference types and instances of value types may be declared only as members of a class or struct or locally in a member function.
C and C++ allow type instances to be declared in global scope, in a namespace scope, and as members of a class or struct or locally in a global or member function.
</t-b>
<h3 id="access">Data Access:</h3>
<t-b>
Access to data is controlled by the scope in which it resides:
<ul class="indent">
<li>
<strong>Global and Namespace Scope:</strong><br />
C and C++ support access by any code in a compilation unit to data defined in the global scope and in namespace scopes. Access beyond the data's compilation unit
will depend on declarations in a header file and the use of the keyword static in the data declaration. C# and Java do not support placing data declarations in global
or namespace scopes.
</li>
<li>
<strong>Class and Struct Scope:</strong><br />
Private member data is accessible only to code in member functions, but is accessible everywhere in that code. Protected member data allows access by all code
defined in derived classes as well, and public member data is accessible to any code below the declaration of an instance of the class in its scope as well as
all the member code in the class and its derivations. Non-static member data
is unique to each instance of the class.
</li>
<li>
<strong>Static Member Data:</strong><br />
The values of static member data of a class or struct are shared by all instances of that type.
</li>
</ul>
</t-b>
<h3 id="sharing">What do we mean by Global Sharing?</h3>
<t-b>
It's relative. Data defined outside any class, struct, or global function, is global to the program. Non-static member data is global to the instance of its
class or struct. Static member data is global to the set of all instances of its type.
Data defined inside the scope of a function is global to all code in the function after the point of its declaration.
</t-b>
<t-b>
I expect that most developers and language enthusiasts mean program global access when they use the term "global". Note that a database provides
program global sharing of data. Its use is subject to some of the same problems as raw data, although most database facilities provide safe multi-threaded operation.
</t-b>
<h3 id="sowhat">So What?</h3>
<t-b>
The difficulties we encounter with shared data depends largely on its scope of definition. Data defined in a program's global scope is the most likely to
cause difficulties in development and maintenance, as cited in "Problems with Global Sharing", above. As the scope of access is reduced the problems become
easier to manage; and for local and non-static member data, in small functions and classes, almost non-existent because the entire scope is
designed and implemented by one person at one time in a page or two of code.
</t-b>
<t-b>
Constant data defined in the global scope causes no problems and has semantic value, providing a program-wide name for an invariant. Global data with a
single writer has only one specific problem - a value intended for one reader may be overwritten with a value for another reader before the first is read.
</t-b>
<t-b>
Using global data with multiple writers and readers should almost always be avoided because its just too hard to understand and manage.
Java and C# prohibit all use of global data, even the beneficial use of global invariants.
</t-b>
<t-b>
Sharing through static member data can be very useful. Here's an example.
<div class="indent">
<t-b>
We've decided to communicate between two processes in our application using
enqueued messages. There may be several parts of the sending process's code that need to create and post messages. If they are in different scopes how
do they all access the queue?
</t-b>
<t-b>
It would be hard to make a simple elegant design that passed references to the queue into every scope that needs access.
If we write a small wrapper class that holds a static instance of the queue and makes it available, the code in any other scope that needs access can
simply declare an instance of the wrapper class to get to the queue. If the queue is thread-safe, then the wrapper becomes very easy to use.
</t-b>
<t-b>
In C++ we can declare the wrapper as a template type that takes an integral type
as a template parameter. That will create seperate types for each value of the parameter and so we can define queues that are shared by different
categories of users, e.g., those that need acess to an input queue and those that need access to an output queue.
</div>
</t-b>
<h3>Summary:</h3>
<t-b>
Use program global data only for program invariants, e.g., initialized once and read many times. Use static member data to share between instances and
provide access to a facility, like a queue, across program scopes. But, be aware of threading issues with static member data. While virtually all programs
beyond the "Hello" variety need shared data, we should attempt to minimize and localize its use as much as possible.
</t-b>
<div style="height:1.0em;"></div>
<img class="photo" src="Pictures/slocum.jpg" alt="Newhouse" style="width:calc(100vw - 9em);" />
<div style="height:1em;"></div>
<a id="bottom"></a>
</content>
<page-TOC id="pages" style="display:none;">
</page-TOC>
<page-sections id="sections" style="display:none;">
<menu-elem style="width:0.0em"> </menu-elem>
<menu-elem class="secElem"><a href="#bottom">bottom</a></menu-elem>
<menu-elem class="secElem"><a href="#sowhat">sowhat</a></menu-elem>
<menu-elem class="secElem"><a href="#sharing">sharing</a></menu-elem>
<menu-elem class="secElem"><a href="#access">access</a></menu-elem>
<menu-elem class="secElem"><a href="#scopes">scopes</a></menu-elem>
<menu-elem class="secElem"><a href="#globals">globals</a></menu-elem>
<menu-elem class="secElem"><a href="#top">top</a></menu-elem>
<div class='darkItem popupHeader' style="padding:0.25em 2.0em;" onclick="this.parentElement.style.display='none'">Sections</div>
</page-sections>
</main>
<frame-footer>
<menu-item style="width:2.0em;"> </menu-item>
<menu-elem id="nextLink2" onclick="bottomMenu.next()">Next</menu-elem>
<menu-elem id="prevLink2" onclick="bottomMenu.prev()">Prev</menu-elem>
<menu-elem id="pgbtn" onclick="bottomMenu.pages()">Pages</menu-elem>
<menu-elem onclick="bottomMenu.sections()">Sections</menu-elem>
<menu-elem onclick="bottomMenu.about()">About</menu-elem>
<menu-elem id="kysbtn" onclick="storyHlpMenu.keys()">Keys</menu-elem>
<menu-elem style="margin-right:1em">
<span id="loc" style="display:inline-block; font-weight:normal"></span>
</menu-elem>
</frame-footer>
</page-frame>
<script>
let loc = document.getElementById("loc");
let fn = window.location.href.split(/\/|\\/).pop();
loc.innerHTML = fn + ":";
</script>
</body>
</html>