referencing and .retention in block-structured coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf ·...

30
Referencing and .Retention in Block-Structured Coroutines GARY LINDSTROM The University of Utah and MARY LOU SOFFA The University of Pittsburgh The combination of coroutines with recursive procedures is characteristic of many modern higher level languages offering advanced control structures (e.g., SIMULA-67, SL5, or INTERLISP). We say a language has block-structured coroutines (BSCRs) when static nesting considerations govern the usage of this control combination. Starting with the BSCR control description work of Wang and Dahl, this paper pursues further the implications of static program structure on BSCR programs in a particular compilation-oriented setting. Disciplines on BSCR reference assignment and individual control actions are defined, offering enhanced implementability and program comprehensibility. Of particular interest is a scope-based discipline on "detach" operations, which avoids the formation of idle chain subheads, an implementationally undesirable condition. The retention requirements of BSCRs are analyzed under a range of possible remote accessibility conditions, and two deletion strategies are then defined, keyed to these requirements. The first uses a special form of scope- sensitive reference counting, and the second does mark-sweep garbage collection, again exploiting static program structure. Space and time estimates for both methods are given, along with avenues for continuing research. Key Words and Phrases: coroutines, static nesting, deletion strategies, reference counting, garbage collection, remote accessing CR Categories: 4.12, 4.22 1. INTRODUCTION 1.1 Importance of Logical Parallelism Logical parallelism as a programming concept is growing in importance as higher level programming languages (HLLs) become more widely adopted. Application areas such as systems programming, real-time control, simulation, and heuristic searching are but a few of the domains better served by HLLs possessing control Permission to copy without fee all or part of this material is granted provided that the copies are not made or distributed for direct commercial advantage, the ACM copyright notice and the title of the publication and its date appear, and notice is given that copying is by permission of the Association for Computing Machinery. To copy otherwise, or to republish, requires a fee and/or specific permission. This work was supported in part by grant MCS-78-03832 from the National Science Foundation to the University of Utah and grant MCS-79-06102 from the National Science Foundation to the University of Pittsburgh. Authors' addresses: G. Lindstrom, Department of Computer Science, The University of Utah, 3160 Merrill Engineering Building, Salt Lake City, UT 84112; M. L. Sofia, Department of Computer Science, University of Pittsburgh, Pittsburgh, PA 15260. © 1981 ACM 0164-0925/81/0700-0263 $00.75 ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981, Pages 263-292.

Upload: others

Post on 13-Jul-2020

4 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and .Retention in Block-Structured Coroutines

GARY LINDSTROM

The University of Utah

and

MARY LOU SOFFA

The University of Pittsburgh

The combination of coroutines with recursive procedures is characteristic of many modern higher level languages offering advanced control structures (e.g., SIMULA-67, SL5, or INTERLISP). We say a language has block-structured coroutines (BSCRs) when static nesting considerations govern the usage of this control combination. Starting with the BSCR control description work of Wang and Dahl, this paper pursues further the implications of static program structure on BSCR programs in a particular compilation-oriented setting. Disciplines on BSCR reference assignment and individual control actions are defined, offering enhanced implementability and program comprehensibility. Of particular interest is a scope-based discipline on "detach" operations, which avoids the formation of idle chain subheads, an implementationally undesirable condition. The retention requirements of BSCRs are analyzed under a range of possible remote accessibility conditions, and two deletion strategies are then defined, keyed to these requirements. The first uses a special form of scope- sensitive reference counting, and the second does mark-sweep garbage collection, again exploiting static program structure. Space and time estimates for both methods are given, along with avenues for continuing research.

Key Words and Phrases: coroutines, static nesting, deletion strategies, reference counting, garbage collection, remote accessing CR Categories: 4.12, 4.22

1. INTRODUCTION

1.1 Importance of Logical Parallelism

L o g i c a l p a r a l l e l i s m a s a p r o g r a m m i n g c o n c e p t is g r o w i n g i n i m p o r t a n c e a s h i g h e r

l e v e l p r o g r a m m i n g l a n g u a g e s ( H L L s ) b e c o m e m o r e w i d e l y a d o p t e d . A p p l i c a t i o n

a r e a s s u c h a s s y s t e m s p r o g r a m m i n g , r e a l - t i m e c o n t r o l , s i m u l a t i o n , a n d h e u r i s t i c

s e a r c h i n g a r e b u t a f e w o f t h e d o m a i n s b e t t e r s e r v e d b y H L L s p o s s e s s i n g c o n t r o l

Permission to copy without fee all or part of this material is granted provided that the copies are not made or distributed for direct commercial advantage, the ACM copyright notice and the title of the publication and its date appear, and notice is given that copying is by permission of the Association for Computing Machinery. To copy otherwise, or to republish, requires a fee and/or specific permission. This work was supported in part by grant MCS-78-03832 from the National Science Foundation to the University of Utah and grant MCS-79-06102 from the National Science Foundation to the University of Pittsburgh. Authors' addresses: G. Lindstrom, Department of Computer Science, The University of Utah, 3160 Merrill Engineering Building, Salt Lake City, UT 84112; M. L. Sofia, Department of Computer Science, University of Pittsburgh, Pittsburgh, PA 15260. © 1981 ACM 0164-0925/81/0700-0263 $00.75

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981, Pages 263-292.

Page 2: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

264 Gary Lindstrom and Mary Lou Sofia

structures that go beyond a purely stack-based hierarchy. The term coroutine, originally introduced by Conway [6] to characterize the coexistent phase organi- zation often found in compilers, is commonly used to describe such logically parallel program units.

When coupled with recursion in HLLs, coroutines become an extremely flexible tool for algorithm specification. In such a combination recursion contributes dynamic storage allocation and hierarchical environment sharing, while corou- tines contribute control versatility within those environments. From these two bases a remarkably wide range of control effects can be achieved, including backtracking [10], pattern-directed invocation [16], and deferred evaluation [9], among many others.

While this versatility is clearly an asset, it is also a liability in that poorly structured control regimes can be encouraged. Thus, while languages of this variety possessing purely dynamic control semantics have obvious experimental merit (e.g., SL5 [11]), other languages incorporating coroutines into more com- pilation-oriented languages with static block structure are likely to have greater ultimate impact. We term this class of languages block-structured coroutine (BSCR) languages. Within this domain, SIMULA-67 [8] offers the most ad- vanced design generally available today.

1.2 Disciplines on BSCR Usage

SIMULA-67 illustrates well the benefits to be obtained by placing disciplines on BSCR usage. These benefits include

(1) implementation economies (such as compile-time reference security); (2) useful semantic concepts offering structure (such as "operating chain," "at-

tachment" versus "detachment") in an otherwise amorphous control domain; and

(3) convenient control "packages" of higher level notions (such as the time-based pseudoparallel control in the system class SIMULATION).

A formal description of SIMULA-67's control behavior (in part) has been offered by Wang and Dahl [23]. However, this early work focused on points (2) and (3) above and ignored such issues as reference variable scoping rules and the enforcement of control event disciplines. While we do not here seek to give a full description of SIMULA-67's control structures, nor even a proper subset thereof,

• we do address these issues and others, both conceptual and implementational, in a BSCR setting chosen especially to exploit program static structure.

1.3 Overview

We begin by reviewing Wang and Dahl's axiomatic method for describing BSCRs in Section 2 and make some clarifying observations on possible BSCR control states. The method is extended in Section 3 to include coroutine instance reference variables, constrained to obey certain static scoping rules. The imple- mentation of our selected control event and reference scoping disciplines is treated in Section 4. As a prelude to the consideration of BSCR deletion strategies, we present postulates in Section 5 that define the retention requirements of our class of BSCRs. In Section 6 an incremental deletion strategy ~', based on a new ACM Transact ions on Programming Languages and Systems, Vol. 3, No. 3, Ju ly 1981.

Page 3: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 265

scope-based approach to reference counting, is described. Since ~ ' is not complete (in that it overlooks certain cyclic structures), a companion method ~", based on a form of scope-based mark-sweeping (garbage collection), is presented in Section 7. Section 8 provides a summary and evaluation of our results.

1.4 Visibility and Scoping

Our treatment here is based on the following range of identifier visibility and program nesting rules.

(1) For simplicity, we assume that coroutine definitions are the only program units involving scoping (since blocks and procedures are logically subsumed). Moreover, we assume that the program consists of a single textually nested set of such definitions (hence separate compilation is ignored).

(2) All variables must be explicitly declared local to some coroutine definition. Creation of a coroutine instance causes the creation of an instance of each locally declared variable, which is d i rec t l y access ib le via its associated identifier through- out the static scope of that coroutine instance (barring redeclaration of that identifier).

(3) A coroutine reference variable may be assigned the name of any coroutine instance in whose static scope it lies, or that of an immediate static descendant of such an instance.

(4) We consider three distinct policies concerning the r e m o t e access of a variable through a reference variable holding the name of the coroutine instance local to which it was created:

Policy (a): no such remote access is permitted; Policy (b): remote access is permitted only to nonreference variables; and Policy (c): remote access is permitted to all variables.

1.5 Previous Work

There has been a wide variety of approaches to the formulation of coroutines; indeed, the title of McIlroy's unpublished but widely circulated memo accurately reflects the situation to this day [17]. Of the few approaches dealing explicitly with scoping issues, the work of Krieg [14] and Vanek [22] is most notable. The latter is of particular interest as a contrast to this work, since in Vanek's approach BSCRs are defined without appeal to programmer-manipulatable reference var- iables.

Approaches to coroutine implementation based on reference counting may be found in [2, 12]; coroutine implementation through garbage collection is studied in [1, 3]. A mixed strategy involving both reference counting and garbage collection may be seen in [4]. Verificational aspects of coroutine programming have been approached in [5, 7].

2. PRELIMINARIES

2.1 Wang and Dahl's Approach to Control Description

Wang and Dahl approach the description of BSCRs by considering an abstract representation of run-time control states. This representation consists of the set

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 4: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

266 Gary Lindstrom and Mary Lou Sofia

of dynamic procedure I ins tances (activations) in existence at any momen t and key relationships tha t exist among those instances. The relationships of interest are the dynamic (i.e., control) and static (i.e., textual) connections among the instances.

2.1.1 Primi t ive Symbols . Following the notat ion of Wang and Dahl, we make use of the following primitive symbols:

£f the set of all procedure instances in existence at any moment ; x.SC, for x E 5z the return l ink of x, a pair of the form

[ip: re turn code pointer, ep: calling instance];

D a function 5P---> 5 z denoting dynamic enclosure (called --> caller), with D(x) - x.SC.ep;

P the processor, in 5z by extension. By special convention, P.SC.ep - D(P) - the currently operat ing instance, and P.SC.ip - the p r o g r a m counter of P;

T a function ~ - {P} --> $z denoting static enclosure (dec lared-- ) declarer);

--~ a binary relation on ~ defined to be x --~ y --- x ~ P A D(x) = y; its transitive closure is x ---)+ y - x --> y V (x ~ P A D(x) ---)+ y), and its transitive and reflexive closure is x -o* y =- x = y V (x ~ P A D(x) ---)* y); a binary relation on ~ defined to be x ~ y --- x ~ P A T(x) = y; its transitive closure is x ~ + y =- x ~ y V (x ~ P A T(x) ~ + y), and its transitive and reflexive closure is x ~ * y = x = y V (x ~ P A T(x) ~ * y). We define v(y) = {x I x ~ * y}; and

OC the set of instances dynamically linked from D(P), tha t is, (Y l D(P) -o* y}, is te rmed the operat ing chain (OC). An instance x is said to be active iff x E OC. If x is active and x --~+ y, we say y is "to the right of" x on the OC.

2.1.2 Control Events . Using this notation, we can characterize a class of possible control events. These comprise instance creation (procedure invocation), instance termination, and the coroutine control exchange actions swap(x) and ro t a t e (x , y). Initially, D(P) = P.

(1) invocation: Assume D(P) = y and y invokes a procedure x declared local to an instance z. More precisely, x refers to a procedure closure consisting of a code entry point code(x), and a static environment env(x), equal to z, providing a data context for accesses of nonlocal variables from within instances of x. Then the result of an invocation of x is the creation of a new instance x of x, adjoined to ~, with T(x) := z, x.SC := D(P) .SC (thereby setting D(x) = y), and P.SC := [code(x), x]. See Figure 1.

l Blocks in the ALGOL-60 sense are considered here to be subsumed by the more general notion of procedures. Moreover, since recursion can readily be simulated by LIFO coroutine control, we assume every procedure instance is created as a coroutine.

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 5: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 267

Fig. 1. Invocation. Dynamic enclosure is indicated by single-stroke arrows and textual enclosure by double-stroke arrows.

(a)

(b)

Fig. 2. s w a p ( x ) . T h e t rans i t ion f rom s ta te (a) to s ta te (b) or vice versa is accompl ished by the same action. T links are not shown.

(2) termination: Assume D(P) = x ~ P. T h e te rmina t ion of x causes P .SC to be set to x.SC and x to be deleted f rom ~.

(3) swap (x ) : Th is event causes the SC var iables of x and P to have their values interchanged, tha t is,

x.SC P.SC

If x ~ OC, the effect of s w a p ( x ) is a re tu rn of control to its caller wi thout t e rmina t ion of x (i.e., x "detaches") . x.SC saves the reactivation po in t of x.

I f x ~ OC, the effect of s w a p ( x ) is the es tab l i shment of D(P) as the current caller of x and the resumpt ion of x at its react ivat ion point (i.e., x is "called"). See Figure 2.

(4) r o t a t e ( x , y): This event causes the SC var iables of x, y, and P to have

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 6: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

268 Gary Lindstrom and Mary Lou Sofia

(Fq-4- -I 14--t x 14-4.1

Fig. 3. r o t a t e ( x , y ) .

their values permuted as indicated below:

P.SC %

x.SC y.SC

The effect of ro ta te (x , y) is equivalent to swap(x) followed immediately by swap(y ) in an indivisible action. See Figure 3.

2.2 Selected Previous Results

2.2.1 L a w a n d Order . In the interest of semantic coherence and enhanced implementability, Wang and Dahl define four "law-and-order" invariants that circumscribe the range of desirable run-time control states. These are

(LO1) P ~ 5z; the processor is never deleted; (L02) D is 1-1; all instances are linked by D into one or more cycles; (L03) for all x ~ P: T (x ) E ~; instance deletion observes static nesting order;

and (L04) for all x # P: D(x ) ~ * T(x), a subtle condition relating D and T link

nesting.

2.2.2 Con t ro l E v e n t Cond i t i ons . Certain conditions are imposed on control events in order to provide a run-time discipline that will ensure the law-and-order objectives listed above. Assume D ( P ) = w. Then these conditions are

(1) c a n i n v o k e (CI): whenever the language permits w to invoke a procedure x, with e n v ( x ) = z, we may be sure that w 7 " z; we denote this by w CI x D w ~ * e nv (x ) ;

(2) can s w a p ( C S ) : w C S x ~ w T * T(x) ;and (3) c a n r o t a t e (CR): w CR (x, y) D w ~ * T (x ) ~ * T ( y ) .

Wang and Dahl prove that these control event conditions are sufficient to preserve (LO1)-(LO4). The following fact, which will prove useful to us subse-

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 7: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 269

quently, is also established:

(LO5) For all w, x: w E OC A w 7 " x D w --** x.

Th is condition s ta tes tha t all T links on the OC are local to the OC and point to the right.

2.2.3 T h e D e l e t i o n S t r a t e g y ~ . As ment ioned in Sect ion 2.1.2, instance termi- nat ion includes the act ion of deleting tha t instance f rom ~. Wang and Dahl extend this deletion policy to a more comprehens ive policy ~ t ha t provides for deletion of instances located off the OC:

~: Assume D ( P ) = x ~ y, x ~ P . As the (only) result of the te rmina t ion of x, P .SC := x.SC ( thereby set t ing D ( P ) = y), and r(x) is deleted f rom Y.

is then proved to be "safe," in the sense t ha t (LO1)-(LO4) are preserved. One corollary (via (LO2)) is tha t ~ always deletes entire D cycles.

2.3 T Link Relationships Among Chains

Law-and-order conditions (LO1)-(LO5) imply a certain s t ructural regular i ty on T l i n k relat ionships among chains. We summar ize this s t ruc ture for fur ther reader or ienta t ion and to aid in la ter sections. First, a few addit ional definitions:

chain(x), x ~ ~ denotes {y E SP I x --~* y V Y --~* x}; hence chain(P) = OC; denotes the set of i d l e c h a i n s , defined to be {chain(x) Ix E SP/X chain(x) ~ OC};

c# denotes the set of all chains, tha t is, ~ U (OC} ; h(L), L E aLP denotes the h e a d instance of L, tha t is, the object of the s w a p

(or r o t a t e ) tha t created L; 5¢ ~ denotes the set of all head instances, tha t is, (h(L) I L ~ ~ ) ; and

we extend (without confusion) the relat ion ~ on 5 z to apply as well to ~. Let L, M be in ~. T h e n L ~ M iff L # M and there exist x (5 L, y E M such tha t x ~ y. Similarly, we assume ~ + and ~ * to be extended to ~ as well.

We now show tha t ~ imposes a t ree s t ructure on ~ as it does on ~.

THEOREM 1. T l i n k s o n O C do n o t cross . M o r e f o r m a l l y , f o r a l l x, y E OC:

x ~ * y ~ * T ( x ) ~ * T ( y ) D x = y V Y = T ( x ) V T ( x ) = T ( y ) .

PROOF. Suppose not. T h e n there mus t exist instances x and y E OC such tha t x ---)÷ y ---)÷ T ( x ) ---~+ T ( y ) ; call this p roper ty TCross(x, y). Select x and y such tha t for no z: x --->+ z ---)+ y, TCross(x, z), or TCross(z , y). I f x ~ y, (LO4) is clearly violated. Otherwise,

C a s e 1. For all z such tha t x ---~+ z ----)+ y, z --->+ T ( z ) ---->* y. T h e n D ( x ) =~* y;

since y --) + T ( x ) --->÷ T(y) , D ( x ) =26* T(x), contradict ing (LO4). O

C a s e 2. For some z: x ---) ÷ z ---)+ y, z ---*+ y ---~ + T ( z ) . But then i f y --->+ T ( z )

---)÷ T ( y ) , TCross(z , y); if T ( y ) ---~* T ( z ) , TCross(x, z). Since these are the only two possibilities for T ( z ) by (LO5), our choice for x and y is contradicted. []

COROLLARY 1.1 w --~* z -->* x E O C / k w 7 " x D z ~ * x.

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 8: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

270 Gary Lindstrom and Mary Lou Sofia

COROLLARY 1.2 Let L be in ~. Then (1) T(h(L)) ~ L and (2) for all z ~ L, T(z) E L V T(z) = T(h(L)) .

PROOF

(1) Let h(L) = x. Then , at the creat ion of L, D(P) ~ * T(x), by CS or CR. Since x E OC at tha t t ime, by (LO5) we have D(P) ---** x ---~+ T(x). Hence T(x) = T(h(L)) r emains on the OC when L is formed.

(2) Suppose not. Then , for some z E L, a t the creat ion of L we have D(P) --** z --->+ x --*+ T(z) , by (LO5). Since D(P) ~ * T(x), by Corol lary 1.1 necessari ly z ~ * T(x). Clearly z ~ T(x), so T(z) 7 " T(x) . By hypothesis , T(z) ~ T(x) = T(h(L)), so T(z) ~ + T(x). T h e n again by (LO5) we have z --*+ x --*+ T(z) --*+ T(x), contradict ing T h e o r e m 1. []

THEOREM 2. The relat ion ~ forms a tree on cd.

PROOF. Le t the node set of the t ree be ~d, and let an arc be presen t f rom L to M iff L ~ M. By (LO5), the OC has no outgoing arcs; this is the root of our tree. By Corol lary 1.2, if L E ~ , then L ~ M iff T(h(L)) E M. Hence the outdegree of L is one, and we have a tree. []

3. REFERENCING

3.1 Reference Variables

In the formal i sm of Sect ion 2, specific procedure instance naming mechan i sms at the source p rog ram level ( tha t is, for use in s w a p ( x ) and r o t a t e ( x , y)) are not considered. N a m e s of procedure instances, however, are dynamica l ly crea ted and mus t be man ipu la t ed th rough the use of reference variables as intermediar ies . We now extend our formal i sm to deal explicitly with such variables. Our goal here will be to sharpen the control event definitions and condit ions of Sect ion 2 in p repa ra t ion for thei r efficient imp lemen ta t ion in Sect ions 4 th rough 7.

3.1.1 Notat ion. T h e following addi t ional nota t ion is needed:

symbols in lowercase script le t ters denote reference variables, t ha t is, those pe rmi t t ed to assume procedure instance names as values;

t(D denotes the instance containing the declara t ion of e as a local variable; g~ (for " env i ronmen t descr iptors") denotes the set of all reference vari-

ables current ly existing (i.e., local to any existing instance); e÷ denotes the instance current ly referenced by ~; ~÷ m a y also be the

special value nil, which is the initial value of all e E •; stat(x) for x E 5 p denotes the static depth of x, defined to be

s ta t (P) = 0; stat(x) = s ta t (T(x)) + 1 for x ~ P;

disp(x, i) for x ~ 5z and 0 < i <_ stat(x) denotes the instance stat ically enclosing x a t dep th i; t ha t is,

T stat(x)-i(x);

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 9: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 271

(disp(D(P), • ) is the display vector of P, used in most block structure implementat ions for accessing the variables nonlocal to the currently operating instance [19].)

3.1.2 Scoping Considerations. We now define a notion of textual scoping for reference variables. In a manner similar to that employed in ALGOL-68 [21] and SIMULA-67 [8], we insist tha t the procedure instance immediately surrounding (statically) an instance x must also surround the declaration of any variable e .that references x. We formalize this constraint as follows through a "can refer- ence" (CRF) relation on # x 5#:

e CRF x ~ t(e ) 7 " T(x).

By ordinary identifier scoping rules, a relation similar to CRF must exist between the currently operating instance and the instance within which any directly accessible reference variable e is declared. Without confusion, we extend CRF to express this relation on 5: x # as well:

D(P) CRF e ~ D(P) 7 " t(e ).

Note that, by transitivity of ~ * , we have

D(P) CRF ~ CRF x ~ D(P) 7 " T(x).

Thus the range of instances directly referenceable from D(P) is a subset of those whose declarations are accessible by ordinary block structure considerations. Moreover, every x such that D(P) 7 " T(x) is accessible if by foresight (1) there are no intervening identifier clashes and (2) an e is present at some appropriate block level (e.g., T(x)) referencing x.

Instances may be indirectly referenced from D(P) through a variety of language structures, including parameter mechanisms and remote accessing (e.g., "e.i" constructs in SIMULA-67). While instance accessibility through parameters is not considered here, several implications of remote accessing are discussed in Sections 5 through 7.

3.1.3 Operations on Reference Variables. Two primitive operations are de- fined on d~:

(1) r e m r e f e ("remove reference"), where e¢ = y ~ 5: (i.e., e¢ # nil): the reference to y is cleared from e, and nil is installed in its place.

(2) e s e t r e f a ("set reference"), where e ¢ = nil and a is an expression evaluating to the name of some y E 5f: if e CRF y, then e is made to point to y (otherwise, an error occurs).

Note tha t for our later implementat ional convenience we assume r e m r e f is never done when e + = nil; similarly, e s e t r e f a is done only when e ÷ = nil and a has a non-nil value. Thus an arbitrary s ta tement of the form e := a would correspond to the code sequence

i f e + ~ n i l t h e n remrefe; i f ~ ~ n i l t h e n ~ setref~.

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 10: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

272 Gary Lindstrom and Mary Lou Sofia

3.2 Control Events with Referencing

3.2.1 Extended Defini t ions. To support the mechanics of referencing, we choose to make the following changes to the specifications of Section 2.1.2:

(1) invocation: Assume D(P) = y and y has access to a procedure closure x = [code(x), env(x)]. T h e n an invocation of x, denoted n e w x, causes the following actions: a new instance x of x is created (adjoined to 5°), T(x) := env(x), x.SC := [code(x), x], and the operator n e w returns x as its value. (A typical application would be of the form e s e t r e f n e w x.) Note that , in contrast to (1) in Section 2.1.2, the execution of x does not commence, since P.SC is unchanged; instead, 2~:= ~ u {x}.

(2) termination: Assume D(P) = y and y terminates. Th en a d e t a c h ( y ) is done (see (3) below), and y.SC.ip := undef ined. Note tha t y is not automatical ly deleted; this is handled more comprehensively in Sections 6 and 7. For our later convenience we denote 9-= {y E 5~ly.SC.ip = unde f ined} .

(3) swap : As indicated in (3) of Sect ion 2.1.2, s w a p is actually a combined specification of two distinct control events, coroutine de tachment and react ivat ion (call). In the interest of program clarity and implementabil i ty, we follow the lead of SIMULA-67 and denote each case separately. Let a be an expression evaluating to some instance y. T h e n

cal l(a) , for y ~ OC: y.SC and P.SC have their values interchanged. Chain(y) is thereby removed from L# and appended to the left end of the OC.

d e t a c h ( a ) , for y E OC: y.SC and P.SC have their values interchanged. Chain(y) is thereby created and adjoined to ~.

(4) r o t a t e ( a , fl): {de tach(a) ; call(fl)} performed indivisibly.

3.2.2 E x t e n d e d Conditions. Our revised control events do not require any changes to be made to the CI condition of Sect ion 2.2.2. However, some modifi- cations are necessary to CS and CR. Moreover , we choose to build in at this t ime an added constraint on idle chain reactivations. I t is programmatical ly impor tan t tha t dynamic enclosure relationships among instances within an idle chain be preserved over tha t chain's creat ion and reactivation. T h a t is, suppose x -*+ y on the OC, and x ~ chain(y) = L ~ ~ a f t e r a d e t a c h (or r o t a t e ) , tha t is, x and y are idled together. T h e n upon react ivat ion of L we wish x -*+ y to hold once more, ra ther than y --.+ x. This policy may be ensured by constraining ca l l to take only arguments which are members of ~ , tha t is, idle chain head instances.

(1) can de tach (CD): Suppose d e t a c h ( a ) is to be executed. T h e n necessarily

(CD1) a must evaluate to some y E ~ ( h e n c e is non-nil in value); (CD2) D(P) 7 " T(y); and (CD3) y E OC.

(2) can call (CC): Suppose cal l(a) is to be executed. T h e n necessarily

(CC1) a evaluates to some y ~ 2z; (CC2) D(P) 7 " T(y); (CC3) y E Jt~; and (CC4) y ~ ~.

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 11: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 273

(3) can ro ta te (CR): Suppose r o t a t e ( a , fi) is to be executed. T h e n necessari ly

(CR1) a evaluates to some x E :7; (CR2) fi evaluates to some y ~ :7; (CR3) D ( P ) 7 " T(x) 7 " T(y); (CR4) x E OC; (CR5) y E 5~z; and (CR6) y ~ 3T.

4. IMPLEMENTING REFERENCING

T h e conditions described in Sect ion 3 m a y be implemen ted efficiently using a combinat ion of compile- t ime and run- t ime checks. We consider each condition in turn.

4.1 CRF

The referenceabi l i ty relat ion CRF has two aspects, as specified in Sect ion 3.1.2.

4.1.1 & × ~. T h e condition e C R F y, tha t is, t(e) ~ * T ( y ) , m a y be checked a t run t ime by verifying tha t stat(t(e)) >_ s t a t ( y ) - 1 and tha t disp(tie), s t a t ( y ) - 1) = T(y) . Note tha t if D ( P ) CRF e (e.g., e is being accessed directly), the tes t can be made in fixed t ime through use of P ' s display vector. Otherwise, this tes t will require stat(t(e)) - s t a t ( y ) + 1 s teps along the T link sequence f rom ti~). 2

4 .1 .2 :7 x #. The condition D i P ) C R F e, tha t is, D ( P ) ~ * t(e}, m a y be checked a t compile t ime as per ordinary identifier scoping rules.

4.2 CC and CD

The verification of conditions (CD1) and (CC1) requires s imply a non-n i l value check a t run time. Condit ions (CD2) and iCC2) can be accomplished as per Sect ion 4.1.1. Condit ion (CC4) is trivial. Condit ions (CD3) and (CC3), however, require some elaborat ion. We assume an 9 ~ m e m b e r s h i p bit in each instance x, denoted Hbit(x) , set by n e w and d e t a c h , and cleared by call .

4.2.1 (CC3). We implement the test for y E 9~ as a run- t ime test for Hb i t (y ) -- 1.

4.2.2 iCD3). Implemen t ing the tes t for y E OC is more challenging, since H b i t i y ) = 0 for bo th y E OC and y E L ~ ~, where y ~ h(chain(y)) . Stepwise t raversa l of the OC looking for y is unat t rac t ive , as is the idea of an OC member sh ip bit. The re is a be t te r approach tha t exploits T h e o r e m 1 and the fact t ha t (CD3) is only tes ted when D ( P ) ~ * T ( y ) .

Suppose D ( P ) 7 " T ( y ) and y E OC is to be verified. Consider each yi @ OC such tha t T(yi) = T ( y ) , numbered f rom left to right. By (LO5), we have D i P ) --)* yl --~+ . . . ---)+ yk ---)+ T i y ) . I f y E OC, y = yi for some 1 _< i _< k. By Corollary 1.1 we find each yi as follows. Let b = s ta t (y ) . T h e n yl -- d i s p i D ( P ) , b), yi+l = d i sp (D(y i ) , b) for 1 _< i _< k - 1, and D(y~) = T ( y ) . Hence a tes t for OC m e m b e r s h i p can be per formed as shown in Figure 4.

2 In t h e s i m p l e c a s e e: = f , w h e r e e a n d f a r e a c c e s s e d d i r e c t l y , n o r u n - t i m e C R F t e s t s a r e n e c e s s a r y i f s t a t ( t ( f ) ) ~_ stat(t(e)).

ACM Transact ions on Programming Languages and Systems, Vol. 3, No. 3, Ju ly 1981.

Page 12: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

274 Gary Lindstrom and Mary Lou Sofia

i s o n O C ( y ) : {test for y E OC, given D ( P ) ~ * T(y)} b e g i n z := D( P) ; foundy := false;

w h i l e z ~ T ( y ) and not foundy do b e g i n z := disp(z, b);

foundy := z = y; z := D(z)

end ; i sonOC := foundy

end

Fig. 4. Opera t ing chain m e m b e r s h i p test.

4.3 CR

Conditions (CR1)-(CR2) and (CR4)-(CR6) correspond directly to similar condi- tions discussed in Section 4.2. We consider now condition (CR3), D(P) 7 " T(x) 7 " T(y ) . In a manner analogous to tha t for (CC2) and (CD2), we implement (CR3) by the following run-t ime checks:

(1) s ta t (D(P)) >_ stat(x) - 1 >_ s ta t (y ) - 1; (2) disp(D(P) , stat(x) - 1) = T(x); and (3) disp(D(P) , s ta t (y ) - 1) -- T(y) .

We observe tha t all these tests can be accomplished in fixed t ime using P ' s display vector. Moreover , we note that , in the special case where ro ta te (e , f ) is being done on two reference variables directly accessible f rom D(P), steps (2) and (3) ma y be eliminated.

THEOREM 3. Suppose D(P) C R F e a n d D(P) C R F ~, wi th e÷ = x @ 5: a n d f ~ = y ~ ~. Then D(P) 7 " T(x) 7 " T(y) i f f stat(x) >_ s ta t (y) .

PROOF. Clearly T(x) ~ * T (y ) implies stat(x) >_ star(y) . Now assume the latter. By CRF, D(P) 7 " t(4 7 " T(x) and D(P) 7 " t(/z) 7 " T(y) . Now ei ther D(P) 7 " T(x) 7 " T(y) , and we are done, or D(P) 7 " T (y ) 7 + T(x). Th e la t ter contradicts our assumption of star(x) >_ s ta t (y) . []

4.4 Idle Chain Subheads

As discussed in Sect ion 4.2, Hbit(x) may be used to detect immediate ly if x E J~ but not if x ~ OC, even given D(P) 7 " T(x). This difficulty is caused by the possible presence of idle chain subheads, which we now define.

Definit ion. Suppose x E L E ~. T h e n x is said to be a subhead of L iff x ~ and T(x) ~ L. By Corollary 1.2, T(x) = T(h(L)).

4.4.1 S u b h e a d Absence. We now argue tha t the absence of idle chain subheads improves the implementabi l i ty of (CD3). Fur the r benefits will become evident in Sections 6 and 7.

THEOREM 4. I f n o subheads exis t on chains in ~ then (CD3) m a y be imple- m e n t e d as an Hbit( y) = 0 test.

PROOF. Clearly, if Hbi t (y ) = 1, y ~ ~ , so y ~ OC. Now suppose D(P) 7 " T (y ) and Hbi t (y ) = 0. T h e n ei ther y E OC, and we are done, or y E chain(y) E ~.

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 13: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 275

Since T(y) E OC, y must ei ther bc in 3~for be a subhead of chain(y). Both are impossible by assumption.

4.4.2 Subhead Creation. Idle chains with subheads are created when d e t a c h e s are done on instances not statically surrounding the current ly operating instance.

THEOREM 5. Suppose D(P) = w 7 " T(y) and a d e t a c h is done on y. Then chain(y) has no subheads iff w 7 " y.

PROOF. Assume chain(y) is formed with no subheads. Th en y E Wand, for all z E chain(y) , z 7 " y. In particular, w 7 " y.

Now assume w 7 " y. Consider any z such tha t w --** z --** y. By Corollary 1.1, z 7 " y. Hence chain(y) has no subheads. []

4.4.3 Preventing Subheads. By Theo rem 5, idle chain subheads can be avoided, with no other loss of flexibility, by enforcing (CD3') D(P) ~ * y ra ther than (CD3) D(P) 7 " T(y). This may be achieved, if desired, in one of two ways:

(1) by adopting (CD3'), with implementat ion stat(y) <_ stat(D(P)) /~ disp(D(P), stat(y)) = y, or

(2) by expressing d e t a c h e s in terms of surrounding block labels, for example,

d e t a c h ( ( procedure identifier))

and

r o t a t e ( ( procedure identifier), ( reference expression ) ).

Option (2) not only is more compilable and avoids awkward run-t ime errors but also yields a more readable, statically comprehensible program text. Similar conventions are now being advocated for exception handling in block-structured languages.

5. RETENTION REQUIREMENTS

In preparat ion for our discussion of reference-based instance deletion strategies, we assess the re tent ion requirements imposed by the referencing and control event conditions described in Section 3.

5.1 Instance Accessibility

Instances must be retained as long as their presence may be instrumental to the program's cont inued execution. Clearly, all instances which may become active must be retained, as must instances containing variables tha t may be accessed from potent ial ly active instances. Such variables are said to be remotely accessed.

To illustrate, assume tha t e + = x and tha t i is an identifier. Let us interpret the nota t ion e.i as denoting the variable declared local to x under i (assuming it exists). The n at least three policies on the legality of e.i are possible:

Policy (a): no remote accessibility is permitted; tha t is, constructs of the form e.i are prohibited;

Policy (b): single-level remote accessibility is permitted; tha t is, e.i is permi t ted if the variable denoted is not a reference variable; and

ACM Transact ions on Programming Languages and Systems, Vol. 3, No. 3, Ju ly 1981.

Page 14: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

276 Gary Lindstrorn and Mary Lou Sofia

Policy (c): mult i level remote accessibility is permit ted; tha t is, e.i.f is permi t ted if e.i denotes a reference variable and e.i.f exists, etc.

Clearly, a severe remote accessing policy such as (a) presents earlier opportu- nities for deletion at the cost of programming flexibility. Policy (c) weights these two features in an opposite fashion. Policy (b) provides an at t ract ive balance, offering certain programming conveniences (e.g., the use of t e rmina ted instances as simple data records) while permit t ing reasonable timeliness in instance dele- tion. An extension to policy (b) permit t ing single-level access of reference vari- ables is briefly considered in Sect ion 8.2.

Note tha t remote access of reference variables does not imply a dispensation concerning conditions CRF, CD, CC, or CR. For example, under policy (c) an action de tach(e . i ) is permi t ted only if (1) D ( P ) CRF e; (2) e÷ -= some x E 5D; (3) e.i denotes some f E 8 such tha t t ( f ) = x; (4) f + = some y @ 3z; (5) D ( P ) 7 " T(y); and (6) y E OC.

5.2 The Sets ~¢cland Md

We may formally define the re tent ion requi rements in our class of BS CR languages with the aid of two subsets of ~ :

da t : the set of instances which at present are not deletable, due to their potent ia l act ivatabil i ty (entrance onto OC), and

Mat: the set of instances which at present e i ther are potent ial ly act ivatable or are referenceable f rom a potent ial ly act ivatable instance.

By inspection of the control events of Section 3 and the remote accessing policies above, we may define da t and Msl to be the smallest subsets of 5 ~ satisfying the following postulates:

(ARI) ~¢c[_C ~at; (AR2) OC __ ~¢at; (AR3) x ~ • A x E da t D chain(x) C zCat; (AR4) Under remote accessing policies (a) and (b):

t(D E d a t a s÷ # ni l D s÷ E Mat;

under policy (c):

t(e) ~ MatA e÷ # n i l D s÷ E Me[;

(AR5) x E Mat A x ~ ~ A x ~ 9-A T(x) ~ 5*cat D x E ~¢c[.

Conditions (AR1)-(AR3) are obvious, and (AR4) follows directly f rom the definition of our remote accessing policies. Condit ion (AR5) embodies (CC3), the relevant condition on call , which is the only means by which instances can become active.

5.3 Instance Deletion and Termination

We now clarify the meaning of instance deletion and terminat ion and define the applicability of such actions in terms of Me[ and ~¢at.

Definit ion. T h e delet ion of an instance x involves its removal f rom 5 p (i.e., the availability of its storage for reuse). Th e t erminat ion of x involves x.SC :=

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 15: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 277

[undefined, x] and Hbit(x) := 1 (i.e., x is made into a singleton idle chain that is no longer callable).

Under policy (a), we may at any time delete instances in ~ - rid. Under policies (b) and (c), we may at any time delete instances in 5P- ~e/and

terminate instances in ~ e l - d c l - Y-(i.e., make 3 = ~ e / - dot).

As mentioned in Section 5.1, policy (a) clearly does present greater opportunity for instance deletion. However, an "aggressive" deletion strategy under policy (a) would pose the problem of either locating (and clearing) all references to an instance in ~ e l - de l prior to its deletion or dealing securely with the problem of "obsolete" references to potentially recycled storage. For this pragmatic reason, we assume henceforth that policy (b), with remote accessing suppressed, serves as the preferred implementation of policy (a). This, in fact, is the primary rationale for policy (b).

5.4 Properties of ~et and Je l

Clearly, the construction of ~ 1 and del can be done through any order of application of (AR1)-(AR5). For our later convenience in inductive proofs, we assume that instances enter ~el and dct one by one and that the following ordering is observed:

(1) (AR1) has top priority (i.e., if x enters d o t - ~e~, then it enters ~ d w i t h o u t delay), and

(2) when (AR2) or (AR3) is applied, the elements of the chain enter de l (and, by (1), ~el) in right-to-left order.

Given this standard construction method, we have

(AR6) I fx enters rid, x = P V T(x) E dclalready.

PROOF. By (2) above, this order will be observed within chains. An instance x with T(x) ~ chain(x) enters det only by (AR5), with T(x) ~ det already by requirement. []

(AR7) I f x enters ~e/, x = P V T(x) E ~ a l r e a d y .

PROOF. We proceed by induction on the assumed construction order of ~e2 and rid. If x ~ P enters ~e~by (AR1), T(x) E ~¢dalready by (AR6); hence T(x) E ~e[ already by assumption (1). Otherwise, x must enter ~e~ by (AR4). No matter which policy is in effect, t(D @ ~ I already. By CRF, t(e) ~ * T(x), so by induction T(x) @ ~el already. []

Given (AR6) and (AR7), we can prove the following useful fact.

THEOREM 6. I f policy (b) (or (a)) is in effect, then (AR4)-(AR5) may be combined as follows:

(AR4') t(e) E d e l A e÷ ~ n i ID ~÷ E ~e~A (e÷ E ~ A e÷ ~ J-D e÷ E det).

PROOF. Since (AR4') includes (AR4), we need only check that (AR4') sub- sumes (AR5) as well. (AR5) is crucial to instances that enter W~t by virtue of first being in ~ Instances enter ~ d - ~¢~l by (AR4). On such an occasion we have

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 16: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

278 Gary Lindstrom and Mary Lou Sofia

t(e) E dcL, with t(~) ~ * T(e÷ ) by CRF. By (AR6), we are sure T(e÷ ) ~ ~c~, so the remaining conditions for (AR5) may be incorporated directly into (AR4'). []

6. SCOPE-BASED REFERENCE COUNTING

6.1 Overview

Wang and D a h r s deletion strategy @ (Section 2.2.3) provides for the deletion of T(x) upon the terminat ion of x. With the introduct ion of referencing, ~ is no longer appropriate because

(1) t e rmina ted instances may no longer be automatical ly deleted if remote referencing is permit ted, and

(2) o ther opportuni t ies for deletion can be occasioned by r e m r e f operations and d e t a c h e s tha t are de facto terminat ions due to loss of instance accessibility.

In this section we define a new deletion strategy @' exploiting a form of scope- based reference counting. While ~ ' is economical and incremental , it is not complete in the sense tha t some deletion opportuni t ies may be overlooked (namely, those involving circular references of a part icular form). Section 7 deals with a companion strategy ~ " tha t ameliorates this shortcoming through a form of scope-based garbage collection.

6.2 Ext Fields

References to an instance x from outside ~(x) have a greater re tent ive influence on x than do those from within T(x). For this reason, we choose to count such instances in a field ext(x). Thus,

ext(x) = {{e{e÷ = x / k t(e) =l~* x}l.

6.2.1 M a i n t a i n i n g E x t Fields. For economically as follows:

(1) ne w: (2) e s e t r e f a, where a evaluates to x:

(3) r e m r e f e, where e ÷ = x:

Again we observe that , if D(P) CRF through the use of P ' s display vector.

each x ~ ~, ext(x) may be maintained

ext(x) := 0 upon creat ion of x; if stat(t(e)) < stat(x) V disp(t(e), stat(x))

x, then ext(x) := ext(x) + 1; and if stat(t(e)) < stat(x) V disp(t(e), star(x))

x, then ext(x) := ext(x) - 1.

e, actions (2) and (3) each take fixed t ime

6.2.2 Explo i t ing E x t Counts. The utility of ext counts in detecting deletion and terminat ion opportunit ies may be seen by the following theorems.

THEOREM 7. X ~ 9~ /~ ext(x) = 0 D x ~ ~

PROOF. Since P ~ ~ , the proposit ion is trivially t rue for x -- P. We proceed by induction on the assumed construct ion order of ~ a n d ~¢c~. Consider the m o m en t when x enters ~e~. If it enters by (AR3) and (AR1), x ~ ~ . Otherwise, it must enter by (AR4), with t(D ~ ~ d already and v+ = x. If t(D =~* x, ext(x) > 0 because of e. Otherwise, t(e) ~ * x, so x E ~e t already by (AR7), a contradiction. []

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 17: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 279

COROLLARY 7.1 I f x E 3¢ ~ a n d ext (x) --- 0, r(x) a n d S a t are dis joint .

PROOF. Follows directly from Theo rem 7 and (AR7). []

COROLLARY 7.2 I f x E H a n d ext(x) = 0, chain(x ) a n d ~¢cl are dis joint .

PROOF. By T h e o r e m 7, x ~ ~e~; hence x ~ Jc~. By (AR3) and (AR5), chain(x) and ~¢c[ are then necessarily disjoint. []

COROLLARY 7.3 I f X E 9¢ ~ a n d ext (x) = 0, r(x) m a y be de le ted , and , for each ' subhead y E chain(x ) , ~(y) m a y be de l e t ed i f e x t ( y ) = 0 a n d t e r m i n a t e d otherwise .

PROOF. By Corollary 7.1, r(x) is disjoint from ~e l and may be deleted. By Corollary 7.2, y ~ ~¢cl for each subhead y E chain(x). Hence v(y) may be terminated. If ex t ( y ) = O, r ( y ) may then be deleted since y will then be a head instance (of a singleton chain).

6 3 .~' Invariants

Before describing the operat ion of ~ ' in detail, we specify its desired behavior through a list of invariants tha t are to be preserved (in addition to (LO1)-(LO4)):

(RC1) for all e E 8, e÷ = ni l V e÷ E 5P; (RC2) for all x ~ ~, ext (x) = I{e E 81 t(D =~* x}l; (RC3) for all L @ ~, ex t (h (L ) ) > 0; and (RC4) for all x E Y,,

(a) D(x) = x; (b) v(x) _C S,, and (c) if policy (b) is in effect, for all e E o ~ such tha t t(D = x, ~÷ = nil.

6 4 Oppor tun i t ies Under .~'

Given properly maintained ex t count fields, the instance deletion and terminat ion opportunit ies provided by Theo rem 7 and its corollaries may be exploited as follows.

6.4.1 Detect ion. There are three occasions upon which the conditions for ~ ' can apply.

(1) r e m r e f e , with e + = x: if ext(x) is brought to zero and x ~ ~ , we may delete r(x) and terminate T(y) for each subhead y in chain(x).

(2) d e t a c h a, with a evaluating to x: if ext (x) = O, we may again delete r(x) and terminate v(y) for each subhead y in the newly created chain(x).

(3) t e r m i n a t e , with D ( P ) = x: if ext(x) = O, we may delete T(x); otherwise, we may terminate T(x).

6.4.2 Effects . The reference counting assumed under ~ ' requires certain effects in instance deletion and terminat ion beyond those defined in Section 5.3. We sharpen these specifications here in preparat ion for their algorithmic accomplish- ment in Section 6.5.

(1) T(x) delet ion: (a) For all e such tha t t(e) ~ * x, i fe¢ # ni l and e÷ =~* x, r e m r e f e .

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 18: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

280 Gary Lindstrom and Mary Lou Sofia

(2) (b) For all y ~ v(x), remove y from 5~. v(x) t e rmina t ion : (a) If ex t (x ) = 0, delete r(x). Otherwise: (b) Under policy (b):

(i) For all e such tha t t(e) = x, r e m r e f e ; (ii) for all y such tha t T ( y ) = x, delete r (y) ; and

{iii) te rminate x. (c) Under policy (c):

(i) For a l l y ~ Y-such tha t T ( y ) = x, te rminate v(y); and (ii) te rminate x.

6.5 Implementing ~ '

The processes of T-tree deletion and terminat ion specified above are highly recursive. Not only are they s ta t i ca l l y recursive in traversing v(x) bu t also d y n a m i c a l l y recursive due to r ipp l ing effects. T h a t is, the deletion of v(x) may cause the deletion (or termination) of a disjoint v(y) to be triggered through a r e m r e f operat ion within r(x). Moreover, the terminat ion of r(x) can cause under policy (c) the cascaded deletion of several subtrees of T(x) in unpredictable order. These effects can cause not only bookkeeping problems bu t also uncontrol led space requirements if not carefully implemented.

6.5.1 T h e W o r k l i s t W. For these reasons we implement T-tree deletion and terminat ion as cooperating algorithms processing a queue of instances needing their at tent ion. We te rm tha t queue the w o r k l i s t W. Fortunately , all such needy instances can relinquish their previous chain membership, so we can implement W as a special pseudochain, with its f ront ( "head") pointed to by W f r o n t and its rear by D ( W f r o n t ) . T h e n

(1) if x E W with ex t (x ) = 0, v(x) is to be deleted; otherwise, v(x) is to be terminated.

(2) We assume W is sorted such tha t s ta t (x ) >_ s ta t (D(x ) ) for x ~ W and x not at the f ront of W.

6.5.2 S e e d i n g W. Instances enter W through one of the three occasions speci- fied in Section 6.4.1. By examinat ion of these conditions, we observe tha t one common algori thm suffices: q u e u e e h a i n (Figure 5). We assume tha t each such program event causes a q u e u e c h a i n invocation, followed by p r o c e s s q u e u e . Rippled r e m r e f s may cause fur ther W loading (via s ch ed u l e ) , but these are handled in due course by the same continuing p r o c e s s q u e u e execution.

6.5.3 R e p r e s e n t i n g v(x). We assume each instance x has two link fields, desc and sib, representing v(x) as follows. Suppose x has k descendants yi, each such tha t T(yi) = x. T h e n

s ib i - l (desc (x ) ) = yi, 1 ~ i <-- k,

and

s ibk(desc(x)) = nil . ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 19: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 281

queuechain(x):

begin local y, z;

{x a head instance; x and subheads of chain(x) are to be inserted into W}

z := D(x); {make z point to left end of chain(x)} schedule(x); {sort x into W} loop y := disp(z, star(x)); {y := next subhead (or x)} exi t i f y = x;

z := D(y); D(y) :=D(x) ; D ( x ) : = y { i n s e r t y i n f r o n t o f x o n W}

end; Hbit(x) := 0 (prevents rescheduling of x}

end

processqueue: {process W doing tree deletions and/or terminations until W is empty}

begin local y; whi le Wfront ~ nil do b e g i n y := D( Wfront); {remove leftmost element of W}

i f y = Wfront then Wfront :~ nil else D(Wfront) := D(y); if ext(y) = 0 then

deletetree( y ) else terminatetree( y )

end end

Fig. 5. ~ ' worklist management (schedule code omitted).

While this unidirectional linking of siblings occasionally causes inefficiency when " random" deletions are to be done, such occurrences are kept to a minimum. T he al ternative is bidirectional linking, which we judge to be unnecessary.

6.5.4 r -Tree Dele t ion. The implementat ion of d e l e t e t r e e ( x ) is given in Figure 6. We make the following observations:

(1) Only x itself within z(x) requires a random deletion from a sibling list. (2) The two-pass nature of d e l e t e d e s c is required so tha t accesses of s tat (e ÷ )

do not occur after e ÷ has been destroyed. If each e carries s tat (e ÷ ) as par t of its value, or if one may be sure the space possessed by instance e ÷ cannot immedi- ately be reallocated, the two passes can be merged.

(3) For efficiency, we implement d e l e t e d e s c recursively. The depth of recur- sion is limited by the program's maximum static depth and therefore represents a known space requirement.

(4) Since W is sorted by nonincreasing s ta t order, W and ~(x) are disjoint. Hence we are free to delete any y ~ r(x) without affecting W.

(5) Since q u e u e c h a i n is invoked only on idle chain heads and elements of W are no longer in H, any instance scheduled via a rippled r e m r e f action must current ly be unscheduled.

(6) A r(x) scheduled for terminat ion may in fact be ready for deletion when reached by p r o c e s s q u e u e if ex t (x ) = 0 by tha t time. If so, deletion occurs ra ther than termination.

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 20: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

282 Gary Lindstrom and Mary Lou Sofia

deletetree(x): {delete all y such that y ~ * x}

b e g i n deletedesc(x, x); {process descendants of x} remove(x, T(x)); {do "random" removal of x as desc. of T(x)} destroy(x) {reclaim x's storage}

end

deletedesc(z, x): { given z ~ * x, clear all refs in T(z) departing r(x), and destroy T(z) except z; all y referenceable from z(z) still exist}

b e g i n local w, y; clearrefs(z, x); y := dese(z); whi le y ~ ni l do {process descendants of z} b e g i n deletedesc(y, x); y := sib(y) end; y := desc(z); whi le y ~ ni l do {destroy immediate descendants of z} b e g i n w := sib(y); destroy(y);

y : = w end; desc(z) := ni l

e n d

clearrefs(z, x): (given z ~ * x, clear all refs in z departing T(x)}

b e g i n local e; for e a c h e such t h a t t(e) = z do

if e + # n i l t h e n

i fstat(e¢) <_ stat(x) a n d e+ ~ x t h e n remre fe end

Fig. 6. Tree deletion within ~ ' ( r emove and d e s t r o y code omitted).

terminatetree(x): {terminate r(x)}

b e g i n local y; term(x); {terminate x itself} y := desc(x); {nil if policy(b) holds} whi l e y ~ ni l do {use W for desc. needing terminate/del.} b e g i n i f ext(y) = 0 or y.SC.ip ~ u n d e f i n e d t h e n

schedule(y); y := sib(y)

end e n d

term(x): {terminate x, tha t is, make into non-CALLable singleton chain} b e g i n x.SC.ip := undef ined ;

D(x) := x; Hbit(x) := 1; i f policy(b) t h e n {only x need be retained}

deletedesc(x, x) e n d

Fig. 7. Tree termination in ~ ' .

6.5.5 T r e e T e r m i n a t i o n . I n c o n t r a s t t o d e l e t e t r e e , t e r m i n a t e t r e e ( x ) c a n

c a u s e s u b t r e e d e l e t i o n s w i t h i n ~(x) i n u n p r e d i c t a b l e o r d e r ( F i g u r e 7). F o r t h i s

r e a s o n , w e e x p l o i t t h e w o r l d i s t W t o p r o c e s s s u c h r i p p l i n g e f f e c t s r a t h e r t h a n

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 21: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 283

through recursion. Again, the static depth order imposed on W is crucial, so tha t we nei ther delete instances while scheduled nor schedule them redundant ly ( thereby malforming W).

6.5.6 Efficiency. As observed above, the space required for the operat ion of ~ ' is proport ional to the maximum program static depth. This remains t rue even if for speed purposes we maintain a Wdisp lay vector permit t ing fixed-time insertion into W.

The t ime required under ~ ' is l inear with respect to the number of instances deleted or terminated, except for

(1) occasional random removals f rom descendant lists ( r e m o v e in d e l e t e t r e e ) and

(2) the examination (once) of each of the previously te rminated immediate descendants of each newly te rminated instance.

7. SCOPE-BASED GARBAGE COLLECTION

7.1 Overview

Delet ion strategy ~ ' just described offers incremental storage reclamation at reasonable space and t ime cost. If sibling reference cycles are not created, or if the parents of such siblings are deleted (or te rminated under policy (b)) before space exhaust ion occurs, ~ ' suffices permanent ly . However, any complete imple- menta t ion of the control forms under discussion must provide a back-up mecha- nism for detecting such cycles and deleting them through a thorough search for sets G2el and dc~.

In this section we present @", a mark-sweep or garbage collection approach to this problem. While an implementat ion may rely solely on ~ " , we assume ~ " supports ~ ' and therefore must observe invariants (RC1)-(RC4) of Section 6.3. As is the case for ~ ' , ~ " exploits the s t ructure of T(P) to economic advantage.

7.2 Marking

We offer two approaches to ~e l and d c t marking. Th e first, M a r k l , directly implements the search implicit in (AR1)-(AR5). Th e second, Mark2 , is optimal in space and time but fails in the special case of the combined presence of multilevel remote accessing and idle chain subheads.

7.2.1 M a r k l . Let us assume the existence of two unused bits in each instance x: ret (x) and act (x), all zero between mark-sweep activations. Th en M a r k l, given in Figure 8, sets ret(x) = 1 iff x E ~ e l a n d act(x) -- 1 iff x E deC. M a r k l may be appraised as follows:

(1) The space requi rement of M a r k l may be criticized because (a) two bits are needed per instance and (b) the mutual recursion between s e t r e t and s e t a c t is bounded only by

[~et[. (A link permuta t ion scheme along the lines of [20] might offer an iterative solution at the cost of added complexity.)

(2) The t ime requi rement of M a r k l may be criticized because the loop in s e t a c t implementing (AR5) prevents M a r k l from running in t ime propor- tional to the number of instances marked.

ACM Transact ions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 22: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

284 Gary Lindstrom and Mary Lou Sofia

s e t r e t ( x ) : (mark x E re t (if no t already) and pursue consequences}

i f re t (x ) = 0 then b e g i n loca l e;

re t (x ) := 1; i f po l i cy ( c ) then {(AR4))

f o r a l l e s u c h t h a t t (e) = x do i f e + ~ n l l t h e n s e t r e t ( e ÷ );

i f x ~ P and H b i t ( x ) = 1 a n d x .SC . ip ~ undef ined and a c t ( T ( x ) ) = 1 then setact(x) {(AR5)}

end

setact(x): {mark x E A c t (if no t already) and pursue consequences}

i f ac t (x ) = 0 then b e g i n l oca l y, e;

ac t (x ) := 1; s e t r e t ( x ) ; {(AR1)} i f H b i t ( x ) = 1 or x = P then {(AR2)-(AR3)} b e g i n y := D(x);

w h i l e y ~ x do b e g i n s e t a c t ( y ) ; y := D ( y )

end end; i f p o l i c y ( b ) then {(AR4))

f o r a l l e s u c h t h a t t (e) = x do i f e÷ ~ n i l t h e n s e t r e t ( e ÷ ) ;

y := desc(x) ; w h i l e y ~ n i l do ((AR5)} b e g i n i f r e t ( y ) = 1 a n d H b i t ( y ) = 1 and y .SC . ip ~ u n d e f i n e d t h e n

s e t a c t ( y ) ; y := s i b ( y )

end end

Fig. 8. Fully general . ~d and do t mark ing unde r ~" ; s ta r t s with s e t a c t ( P ) .

7.2.2 Mark2 . Despite these shortcomings of Mark1 , no be t te r marking algo- r i thm has been found for the general case. If, however, we assume e i t h e r the absence of idle chain subheads or the prohibit ion of multi level remote accessing, ano ther approach exists which is "ideal" in the following senses:

(1) only one mark bit, m a r k { x ) , is used in each instance x; (2) a purely i terat ive algori thm suffices, using only a fixed set of working vari-

ables; and (3) the algori thm runs in t ime proport ional to the number of instances marked.

In a manner similar to tha t used in q u e u e c h a i n {Section 6), M a r k 2 {Figure 9) uses a worklist W of instances scheduled for processing. However, instances enter W by complete chains, ra ther than individually as in q u e u e c h a i n . Although such chains must retain their integri ty after processing, they can temporar i ly be concatenated together with boundaries marked by the Hbi t of each "head" instance. Initially, the OC is put on W. T h e n

(1) we work through W from left to right, marking the current instance x and examining its referenced instances y;

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 23: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 285

Mark2:

begin local front, rear, x, y, e; front := P; rear := D(P); x := rear; loop mark(x) := 1;

for al l e such that t(e) = x do i f e + # n i l t h e n

if mark(e ÷ ) = 0 then b e g i n mark(e+):= 1;

e n d

{single-bit, iterative marking algorithm}

(OC established as W}

ifHbit(e+ ) = 1 t h e n begin {splice chain(e ÷) at front of W)

y := D(e÷); D(e+) := rear; -D(front) := y; front := e+

e n d end;

e x i t if x = front; if Hbit(x) = 1 or x = P then begin {reform chain(x)}

y := D(x); D(x) := rear; D(front) :=y; rear := y; x := y

e n d else x := D(x)

e n d

Fig. 9. Special case ~el marking under ~".

(2) each u n m a r k e d such i n s t ance y is marked , and, if y is a h e a d ins tance , c h a i n ( y ) is p u t on W;

(3) w h e n e v e r the c u r r e n t i n s t ance x has Hbi t (x) = 1, we re form chain(x) as a n idle chain; and

(4) w h e n W is a b o u t to become empty , we hal t .

7.3 Validating Mark2

We now argue the cor rec tness of M a r k 2 . First , th ree def in i t ions .

~veL = { x l x E W a t some t ime du r ing M a r k 2 }

~ a J ~ e d = { x l m a r k ( x ) = 1 af ter M a r k 2 t e rmina tes}

~ ( .~ ) , where ~ _ 5°: {x I for some e such t h a t t(D E .~: ~÷ = x @ 5P}.

T h e v a l i d a t i o n of M a r k 2 involves p rov ing (1) i ts t e r m i n a t i o n a n d (2) t h a t J//a~ea~ = ~el. T h e proof of (1) is tr ivial , s ince W e xpa nds on ly w h e n new cha ins are marked . We prove (2) u n d e r each of the two a l t e r na t i ve p r e c ond i t i ons of M a r k 2 .

7.3.1 M a r k 2 u n d e r P o l i c y (b)

LEMMA 1. I f p o l i c y (b) h o l d s , ~gge~ C d d U 9"- n ~d .

PROOF. By i n d u c t i o n on cha ins b r o u g h t on to W. Ini t ia l ly , W = OC, a subse t of d c l b y (AR2). Now cons ider L E ~9?brought on to W. Necessar i ly , h(L) = ~÷ for some t(e) ~ W. By induc t ion , t(e) E d c t o r t(e) E J . Clear ly t (e) ¢~ J , s ince ~ (~--) = • u n d e r pol icy (b). H e n c e t(D E dc~, an d by (AR4 ' ) we have e+ C ~ d a n d

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 24: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

286 Gary Lindstrom and Mary Lou Sofia

either e ¢ E 3-or e ÷ E rid. If e ÷ E J , then e ÷ is a singleton chain; otherwise, L is a subset o f d d b y (AR3). In either case, the induction is complete. []

LEMMA 2. I f pol icy (b) holds, J g a d ~ C_ . ~

PROOF. By inspection of Mark2 , we observe tha t J/avMe£ = ~qr~U ~ (~qr~ez¢). By L e m m a 1 and the definition of ~ we have J / 4 ~ ___ do t U 3 - n ~ d u ~ (dot) u

( J - n ~el) . Each of these terms is a subset of ~e~ by either (AR1)-(AR4' ) or policy (b). []

LEMMA 3. I f pol iey (b) holds, dctC_ ~qr~e~.

PROOF. By induction on applications of (AR1)-(AR4' ) tha t bring instances into ~¢d. Clearly OC is a subset of dot. Assume that all y currently in d c l are in ~qrae~. If x joins do t by (AR3), necessarily x ~ h(chain(x)), already in dot. Hence h(chain(x)) E ~qF~ed, and so is x.

Otherwise, x must join d o t by (AR4'), with s o m e t(e) ~ d c t already and e÷ = x, x E ~ . By induction t(e) E ~gF~, so chain(x) will enter W when t(e) is current, if not earlier. []

THEOREM 8. I f pol icy (b) holds, ~ e l = J / /a~d .

PROOF. By Lemma 2, JgazAeg _ ~ I t remains to show ~eA _ d / / ~ . By (AR1)-(AR4') , ~eL = do t U ~ (~¢ct). By Lemma 3, ~¢ct___ ~qr~ed, which is a subset of ~ ' ~ . Similarly, ~ (dot) C_ ~ (~qr~eA), which is a subset of J t / ~ . []

7.3.2 M a r k 2 Under S u b h e a d Prohibi t ion

LEMMA 4. X E ~qf~el ~ X = P V T(x) E ~qr~.

PROOF. Follows readily by CRF and induction on instances entering W. []

LEMMA 5. If subheads are prohibi ted, ~ / / ~ = ~/4z~e~.

PROOF. By inspection of Mark2 , ~q~ _ ~ ( a z ~ . We now show that ~az~_~ _ ~q~. Consider x ~ ~//a~e~ - ~qr~_~. Necessarily, for some t(e) ~ ~q~, e÷ = x ¢~ ~ . By CRF, t(e) 7 " T(x); by L e m m a 4, T(x) ~ ~q~e~. If T(x) ~ chain(x), x ~ ~q/~e~, a contradiction. Otherwise x is a subhead, also a contradiction. []

THEOREM 9. If subheads are prohibi ted, ~ / / ~ = ~el.

PROOF. By Lemma 5, we may prove ~qr~e~ = ~ed. Clearly from Mark2 , ~qz~ed_ ~ To show ~ d ___ ~q~, we argue inductively on the formation of ~e~. Initially ~e~= OC, in ~q/~dby initialization of W. Consider now x ~ OC entering ~e~, under the inductive hypothesis tha t ~e2 thus far is a subset of ~q~. If x enters ~e~ by (AR4), t(e) ~ ~ed already and e÷ = x. Hence t(e) ~ ~q/'~, implying x ~ ~ / / ~ , implying x ~ ~/C~ by Lemma 5. Otherwise, x must enter ~ e l by (AR1), implying by our s tandard construction order tha t already h(chain(x)) ~ ~¢cland h(chain(x))

~ By induction, h(chain(x)) ~ ~q~, implying x ~ ~/4~el. []

7 .4 Sweeping

The rules for instance deletion and terminat ion given in Section 5.3 provide tha t at any time we may delete ~ - ~e~ and terminate ~ e t - ~¢cl - ~ . We now examine efficient means for accomplishing this storage regeneration given simply knowl-

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 25: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 287

Sweepl(x): {fast sweep algorithm, applicable if no subheads; given x E Ret, d e l e t e y ~ T(x) w i t h mark(y) = O; clear all mark bits except that of x;

a l l z referenceable from within r(x) still exist}

begin local w, y, z; {recursion and ref clearing pass over desc. list of x}

y := desc(x); w h i l e y ~ n i l do begin i f mark(y) = 0 then { y ~ Ret }

deletedesc( y, y) else sweep l ( y ) ; y := sib(y)

end; {deletion and mark clearing pass over desc. list of x} y := desc(x); z := x; {z trails y on desc. list of x}

w h i l e y ~ n i l do beg in w := sib(y);

i f mark(y) = 1 then {y ~ Ret}

begin mark(y) := O; z :-- y end else { y ~ Ret } begin spliceout(y, z); {remove y from list, using z}

destroy(y) end; y : ~ w

end end

Fig. 10. Special case sweeping under ~"; starts with s w e e p l ( P ) .

edge of ~ e t and J . ~ e l m a y have been determined either by M a r k 1 (ret(x) = 1) or M a r k 2 (mark(x) = 1); notational ly , we assume the latter. J- is , o f course, characterized by x . S C . i p = undefined.

7.4.1 The Set ~ . Let the set of instances needing terminat ion (i.e., ~eA - d o t - 3 - ) be called ~ . We now prove an important property of JVpermitt ing its recognit ion wi thout explicit knowledge of dot.

LEMMA 6. X E Y ~ X ~ P / ~ (T(x) E ~ V x is a subhead) .

PROOF. Clearly x E ~ implies x ~ rid, so x ~ P. Hence T(x) exists and is in ~ I - 9 - b y (AR7) and (RC4b). It remains to show T(x) ¢~ d c l V x is a subhead. If x E ~ , T(x) ~ d c l by (AR5) since x ~ dvl. N o w suppose x ~ ~ ; if x is a subhead, we are done; otherwise T(x) E chain(x) and again T(x) ¢~ d o t since" chains are each either entirely in d c l or entirely disjoint from rid.

7.4.2 Sweep ing with No Subheads . L e m m a 6 leads directly to the fol lowing useful fact:

THEOREM 10. I f idle chain subheads are prohib i ted , ~ is empty.

Given T h e o r e m 10, it is worthwhi le to implement sweeping under subhead prohibit ion as a special case. S w e e p 1 , given in Figure 10, provides an efficient approach that is scope-based; that is, it involves traversal o f T(P). Since we are assuming 9 " is being implemented in support of ~ ' , 9 " mus t decrement ext counts w h e n destroying references to members of ~ However , during the

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 26: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

288 Gary Lindstrom and Mary Lou Sofia

operat ion of @" we do not wish @' to be triggered, so we assume s c h e d u l e calls within r e m r e f are bypassed. As in d e l e t e d e s c , we are cautious not to delete any instance tha t may later have its ext count decremented; hence two passes through each descendant list are used. This would not be necessary if @" were being implemented alone.

The performance of s w e e p l is excellent, since its t ime requi rement is l inear with I ~ I (despite the two-pass approach) and its space requi rement is bounded by the maximum static depth of the program.

7.4.3 Sweep ing wi th Subheads . If idle chain subheads are possibly present, we must see to the terminat ion of X instances. However, this may still be done in a scope-based manner, as shown by the following theorem:

THEOREM 11. I f T(x) E ~ e l - ~ , then x E ~ i f f (1) x E ~e¢, (2) x is a subhead, a n d (3) h(chain(x)) ~ ~e¢.

PROOF. If T(x) E ~ - ~ , T(x) E d~¢ or T(x) ~ YT. If T(x) ~ J , x ¢~ ~ a n d x J , implying x is not a subhead. We now assume T(x) E d c l a n d show both sides

of our equivalence. Suppose x E ~?. T h e n (1) x E ~e4 and (2) x is a subhead by L e m m a 6. Since x J , h(chain(x)) ~ ~, if h(chain(x)) E ~c4 then it would be in d c l by (AR5), as

would x by (AR3). Thus (3) is established. Now suppose (1)-(3) hold. By (1) x E ~el ; by (2) x ~ ~-since Y-members are

singleton chains. By (3) h(chain(x)) ~ ~¢c~, so x ~ ~¢c¢. Hence x E ~ . []

By T h e o r e m 11, we can recognize "top-level" ~ instances by searching for marked subheads on chains with unmarked heads. If these are te rmina ted as encountered, lower level X i n s t a n c e s may be detected by the anomalous condition of T(x) E J a n d x ~ ~.

The search for such top-level ~ instances can be incorporated into s w e e p l as an extra phase performed on the descendants of x when x E ~ e l - ~ - 3-(see the revised algori thm s w e e p 2 in Figure 11). Note tha t this search cannot be combined into the existing phases of s w e e p l , since we cannot recognize a subhead y after chain(y) has begun being broken up.

To est imate the speed of sweep2 , let us assume for the momen t tha t disp computat ions can be done in fixed t ime (e.g., each instance contains its own display vector). Then, despite the two nested loops new to sweep2 , t ime linear with [ ~ [ remains. This is because, within the overall computa t ion of s w e e p 2 ( P ) , the outer loop is executed at most once for each y ~ ~ and the inner loop is executed at most once for each head and subhead in ~. If disp requires T-link searching, we must include this t ime factor, bounded by the maximum static dep th of the program. The space for s w e e p 2 is the same as tha t for sweep1 .

8. SUMMARY AND FUTURE WORK

8.1 Summary

Using the control description approach of Wang and Dahl as a base, we have explored the effects of static program structure on BSCRs in a compilation- or iented setting. Conditions on instance reference assignment (CRF) and individ- ual control actions (CI, CC, CD, CR) were defined and implemented. Th e

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 27: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 289

Sweep2(x): (same condit ions as s w e e p l , except tha t idle cha in subheads are permit ted}

b e g i n loca l w, y, z; i f x.SC.ip ~ u n d e f i n e d t h e n

i f x ~ P and T(x).SC.ip = u n d e f i n e d t h e n t erm(x) (rippled terminat ion}

e l s e (look for w ~ x needing terminat ion} b e g i n y := desc(x);

w h i l e y ~ n i l do b e g i n i f H b i t ( y ) = 1 and mark(y ) = 0 t h e n

b e g i n ( t e rmina te marked subheads of chain(y)} z := D(y) ; l oop w := disp(z, stat(y)); e x i t i f w = y; (w is next s u b h e a d (or y)}

z := D(w); i f mark(w) = 1 t h e n

term(w) end

end ; y := sib(y)

end end ;

( remainder is code of s w e e p l , bu t with recursive call replaced with call on s w e e p 2 }

end

Fig. 11• Fully general sweeping under ~ " ; s ta r t s with s w e e p 2 ( P ) .

retention requirements of our class of BSCR languages were postulated and used as the formal basis for the development of two compatible deletion strategies. The first, ~ ' , uses scope-based reference counting to detect instance deletion and termination opportunities incrementally. The second, @", does mark-sweep gar- bage collection to reclaim isolated cyclic structures overlooked by ~' .

The results obtained here suggest that d e t a c h operations in BSCR languages should refer to program units statically surrounding the currently operating instance• If this design choice is made, then our implementation approaches for both condition testing and instance deletion are highly efficient in both space and time•

8.2 Generalizations

8.2.1 .Control Events Involving Remote Accessing• As remarked in Section 5.1, control events involving remote accessing must obey the same conditions as do those involving direct reference variable access. Thus, if e.i designates some f E d', detach(e.i) would be permitted only if D(P) 7 " T ( /¢ ) . A more liberal language design might remove this scope condition, relying instead on the weaker constraints imposed by CRF. However, (LO4) would no longer hold, and essen- tially all of our results would be invalidated. In fact, SIMULA-67 is even more restrictive than are we, completely disallowing any remote accessing of variables in a class that has another class defined within it. In this way, D(P) 7 " T ( /÷) is guaranteed to hold.

8.2.2 Policy (b'). Policy (b) of Section 5.1 permits only remote accessing of nonreference variables. While this can be useful in simple cases, it precludes the

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 28: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

290 Gary Lindstrom and Mary Lou Sofia

use of t e rmina ted instances as nodes in p r o g r a m m e r - m a n a g e d list s tructures. However , such list processing is typically done on instances derived f rom a single declaration, or at mos t f rom a cluster of re la ted declarat ions appear ing in the same static context. Hence referencing links are in this case " la tera l" in the t ree of T-link relationships, and the full "downward" referencing power of policy (c) is not needed.

We suggest therefore considerat ion of a policy (b ') , in which single-level r emote access is pe rmi t t ed on all variables, including reference variables. T h e appropr ia te var ia t ion of (AR4) in Sect ion 5.2 would be

(AR4") t(~) ~ dc¢A ~4 # nil D e¢ E dcl; t(e) E 9~d A e÷ # nil A T(e÷ ) # t(e) ~ ~+ ~ ~ t ,

which is the (AR4) condit ion for policy (c) with the case T(~+ ) = t(e) excluded. T h e correctness of (AR4") under policy (b ') can be argued by demons t ra t ing

that , if t(D ~ ~ e ¢ - d c l and T(e¢ ) = t(e), instance e÷ need not be retained. B u t there could be only two reasons for such retention: t ha t e÷ migh t become active or t ha t some locals of e + might be r emote ly accessed. T h e first is precluded by t(~) ~ deC. T h e second could occur under policy (b ') only if, for some f E # with t ( f ) E d c t a n d t ( f ) 7 " T(e÷), f ¢ = e¢. But T(~+) = t(e) and, since t(e) ~ dc~, t( f ) ¢~ d~talso.

T h u s the appropr ia te t e rmina t ion effect for ¢(x) under policy (b ') is tha t for policy (b), bu t with the r e m r e f ~ act ion condit ioned upon T(~+) = t(e) (see Sect ion 6.4.2). T h e ~ ' and ~ " a lgor i thms for policy (c) can readily be specialized to fit policy (b ') , t he reby exploiting the earlier deletion oppor tuni t ies offered.

8.2.3 Remote Procedure Calls. In addit ion to list processing, ano the r c o m m o n use of t e rmina ted coroutine instances is the construct ion of modules binding da ta records with procedures operat ing on each such record, as in abs t rac t da ta types. Th is entails r emote procedure calls, a fea ture not addressed in the work jus t presented. However , a s imple nonnes ted fo rm of da ta abs t rac t ion migh t be incorpora ted into policy (b) as follows.

Let ~ E 8, and let e ÷ = x E 5 p with some procedure p declared local to x. Then , if D(P) C R F ~, we m a y call ~.p, creat ing an instance p, if

(1) p is a "pure" procedure, embrac ing no coroutine actions within its dynamic scope, and

(2) x is active or te rminated .

I f x is active, no anomalous condit ions will arise. I f x is te rminated , we will briefly have the anomaly of a T link depar t ing f rom the OC. Since no corout ine act ions will occur during p ' s lifetime, the only difficulty t ha t might arise is the appa ren t deletabi l i ty of x if the final reference to x is r e m r e f e d before p te rminates . This can easily be avoided by nota t ional ly distinguishing such pro- cedures and implement ing such calls as the sequence {3 := n e w ~.p; call(a); r e m r e f ~}, wi th ~ E ¢ and t(z) = D(P), the instance making the r emote call. Since x ~ OC, D(P) =¢** x, so this reference var iable will ensure t ha t ext(x) > 0 for 9 ' , and x will be m a rked under @".

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.

Page 29: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

Referencing and Retention in Block-Structured Coroutines 291

8.3 Future Work

One omission in this work is the consideration of reference-valued parameters. I f , however, these are either excluded or made to obey CRF, our results stand. It may well be fruitful to explore design choices intermediate between this extreme and that of unrestrained reference passage via parameters. One approach might be the explicit declaration of which references can be exported or imported; such constructs are now being advocated as a means toward better program modular- ization.

Another area for continuing work concerns the adaptation of these results to execution environments involving true concurrency [13]. Some preliminary stud- ies have indicated that process reference counting is preferable to garbage collection, in light of the latter's apparently greater need for centralized control [18]. How scoping issues could be exploited in this setting remains unknown.

Finally, additional work is merited on the notion of control discipline necessity given particular implementation strategies. This line of inquiry reverses that explored in this paper, in which sample disciplines were shown to be sufficient to safeguard the correctness of an implementation strategy [15]. With insights in this direction, important questions such as the class of BSCR programs for which 9" is superfluous might be approached.

REFERENCES

1. BAKER, H.G. JR., AND HEWITT, C. The incremental garbage collection of processes. In Prec. ACM Syrup. on Artificial Intelligence and Programming Languages, Univ. Rochester, N.Y., Aug. 15-17, 1977. Published as combined issue: SIGPLAN Notices (ACM) 12, 8 (Aug. 1977), and S I G A R T Newsl. (ACM) 64 (Aug. 1977), 55-59.

2. BERRY, D.M., CHIRICA, L.M., JOHNSTON, J.B., MARTIN, D.F., AND SORKIN, A. Time required for reference count management in retention block-structured languages. Int. J. Comput. Inf. Sci. 7, 1 (1978), 11-64 (Part 1); 7, 2 (1978), 91-119 (Part 2).

3. BERRY, D.M., AND SORKIN, A. Time required for garbage collection in retention block-structured languages. Int. J. Comput. Inf. Sci. 7, 4 (1978), 361-404.

4. BOBROW, D.G., AND WEGBREIT, B. A model and stack implementation of multiple environments. Commun. A C M 16, 10 (Oct. 1973), 591-603.

5. CLINT, M. Program proving: Coroutines. Acta Inf. 2 (1973), 50-63. 6. CONWAY, M.E. Design of a separable transition-diagram compiler. Commun. A C M 6, 7 (July

1963), 396-408. 7. DAHL, O.-J. An approach to correctness proofs of semicoroutines. In Programming Methodol-

ogy, D. Gries (Ed.), Springer-Verlag, New York, 1978, pp. 116-129. 8. DAHL, O.-J., MYHRHAUG, B., AND NYGAARD, K. SIMULA-67: Common base language. Publ. S-

2, Norwegian Computing Center, Oslo, 1968. 9. FRIEDMAN, D.P., AND WISE, D.S. CONS should not evaluate its arguments. Tech. Rep. 44, Dep.

Computer Science, Indiana Univ., Bloomington, Ind., Nov. 1975. 10. GRISWOLD, R.E., AND HANSON, D.R. Language facilities for programmable backtracking. In

Prec. ACM Syrup. on Artificial Intelligence and Programming Languages, Univ. Rochester, N.Y., Aug. 15-17, 1977. Published as combined issue: SIGPLAN Notices (ACM) 12, 8 (Aug. 1977), and S I G A R T Newsl. (ACM) 64 (Aug. 1977), 94-99.

11. HANSON, D.R., AND GRISWOLD, R.E. The SL5 procedure mechanism. Commun. A C M 21, 5 (May 1978), 392-400.

12. INGALLS, D. The Smalltalk-76 programming system. In Prec. 5th ACM Syrup. on Principles of Programming Languages, Tucson, Ariz., Jan. 1978, pp. 9-16.

13. KAHN, G., AND MAcQUEEN, D. Coroutines and networks of parallel processes. IRIA/LABORIA Res. Rep. 202, Le Chesnay, France, Nov. 1976.

ACM Transactions on Programming Languages and Systems, VoL 3, No. 3, July 1981.

Page 30: Referencing and .Retention in Block-Structured Coroutinesdunkels.com/adam/pt/p263-lindstrom.pdf · The term coroutine, originally introduced by Conway [6] to characterize the coexistent

292 Gary Lindstrom and Mary Lou Sofia

14. KRIEG, B. A class of recursive coroutines. In IF IP Congress 74 (Software Booklet), North- Holland, Amsterdam, 1974, pp. 408-412.

15. LINDSTROM, G., AND SOFFA, M.L. Control discipline necessity: Making the language as general as the implementation. In preparation.

16. McDERMOTT, D., AND SUSSMAN, G.J. The CONNIVER reference manual. MIT AI Lab. Memo. 259, MIT, Cambridge, Mass., May 1972.

17. MCILROY, M.D. Coroutines: Semantics in search of a syntax. Unpublished manuscript, 1968. 18. NOR1, A.K. A storage reclamation scheme for Applicative Multi-Processing System AMPS. M.S.

thesis, Dep. Computer Science, Univ. Utah, Salt Lake City, Sept. 1979. 19. RANDELL, B., AND RUSSELL, L.J. Algol 60 Implementation. Academic Press, New York, 1964. 20. SCHORR, H., AND WAITE, W.M. An efficient machine-independent procedure for garbage collec-

tion in various list structures. Commun. A C M 10, 8 (Aug. 1967), 501-506. 21. VAN WIJNGAARDEN, A., MAILLOUX, B.J., PECK, J.E.L., KOSTER, C.H.A., SINTZOFF, M., LINDSEY,

C.H., MEERTENS, LG.L.T., AND FISKER, R.G. Revised report on the algorithmic language Algol 68. ALGOL Bull. 36 (March 1974), suppl.

22. VANEK, L.I. Hierarchical coroutines: A mechanism for improved program structure. Tech. Rep. 99, Computer Systems Research Group, Univ. Toronto, Ontario, Feb. 1979.

23. WANG, A., AND DAHL, O.-J. Coroutine sequencing in a block-structured environment. B I T 11 (1971), 425-449.

Received December 1979; revised September 1980 and January 1981; accepted January 1981

ACM Transactions on Programming Languages and Systems, Vol. 3, No. 3, July 1981.