Data sharing using COROUTINE? 
Author Message
 Data sharing using COROUTINE?

G'day,

It's been quite a while since I've used the COROUTINE library of
Modula-2, and I need a few answers to jog my failing memory.

I'm trying to implement a Modula-2 interpreter in Java, and I've been
using a single stack to handle procedure calls and variables. This is
fine when there is only one thread of control, as any uplevel variable
access can be resolved by traversing the static links of the frames on
the stack.

I'd now like to implement multiple threads to handle the COROUTINES
library. My initial design was to allocate a local stack for each
process, and a shared heap for all processes. Initially, each the stack
of each process would be empty, with new frames pushed onto each local
stack as dictated by the process.

But I'm running into a problem with uplevel variable access ie, a
variable that has been declared outside of the scope of the module or
procedure which acts as the local process. This uplevel variable would
have been allocated on the stack of the process which called its
containing module/procedure, rather than the stack of the process
currently active. So traversing the static links of the local stack (as
per the single-threaded implementation) would no longer work.

Example (using generic process library names) :

  PROCEDURE Outside;
    VAR n: CARDINAL;
        p: Process;
    PROCEDURE Inside();
      VAR m: CARDINAL;
    BEGIN
      (* frame for 'Inside' pushed onto stack s2 *)
      m := n; (* 'm' exists on stack s2, but 'n' is on stack s1 *)
      (* frame for 'Inside' popped off stack s2 *)
    END Inside;
  BEGIN (* Outside *)
    (* 'n' now exists some stack - call this stack s1 *)
    n := 0;
    p := NewProcess(Inside);
    (* 'p' gets its own local stack, initially empty - call it s2 *)
    StartProcess(p);
    ... etc ...
   END Outside;

So: does each coroutine get its own local stack, or does it share the
stack of the process which created it, or some hybrid?

Any thoughts on implementing this, and the semantics/implementation of
COROUTINE in general, would be gratefully acknowledged.

Cheers,
Geoff



Mon, 24 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?

Quote:

> Example (using generic process library names) :

>   PROCEDURE Outside;
>     VAR n: CARDINAL;
>         p: Process;
>     PROCEDURE Inside();
>       VAR m: CARDINAL;
>     BEGIN
>       (* frame for 'Inside' pushed onto stack s2 *)
>       m := n; (* 'm' exists on stack s2, but 'n' is on stack s1 *)
>       (* frame for 'Inside' popped off stack s2 *)
>     END Inside;
>   BEGIN (* Outside *)
>     (* 'n' now exists some stack - call this stack s1 *)
>     n := 0;
>     p := NewProcess(Inside);
>     (* 'p' gets its own local stack, initially empty - call it s2 *)
>     StartProcess(p);
>     ... etc ...
>    END Outside;

SYSTEM.NEWPROCESS expects a procedure parameter of type PROC and this
must not be a local procedure. Thus you don't have the problem of
static links across stacks in Modula-2.

Andreas.

--
Andreas Borchert, Universitaet Ulm, SAI, Helmholtzstr. 18, 89069 Ulm,  Germany

WWW:    http://www.mathematik.uni-ulm.de/sai/borchert/



Mon, 24 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?
I agree with what Andreas says. In addition, as a general point you need
THREE areas of storage:

i)      Global storage for variables declared in definition modules or
outside any procedures. On a classical DOS system this would be
immediately above the code, with the size fixed at compile time.

ii)     A global heap, common to all threads. This will typically have
control of the free memory between static memory (i) and the stack (iii).

iii)    A stack for the main thread/coroutine. Stacks for other coroutines
will be allocated from (i) or (ii). On a classical DOS system this would
be at the top of available memory and grow down.

Bear in mind (a) that Modula-2 coroutines are non-preemptive and (b) that
Modula-2 was designed to use linked stack frames rather than a display
register. I've used a compiler with a display register (actually one per
module if I recall correctly) and it caused a great deal of hassle since
switching coroutines invalidated the display: the result was that it was
unsafe to use WITH or up-level addressing in a block which also contained
a TRANSFER().

Please keep us informed how you get on, sounds interesting. Are you
writing a true interpreter or a compiler to produce Java bytecodes?

-- Mark Morgan Lloyd

--
-- [Opinions above are the author's, not those of his employers or
colleagues]
--
-- ** Internet feed may be unreliable- please cc anything important by
email **



Mon, 24 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?
G'day,

Quote:

> SYSTEM.NEWPROCESS expects a procedure parameter of type PROC and this
> must not be a local procedure. Thus you don't have the problem of
> static links across stacks in Modula-2.

Actually, I remembered after I posted the original message that the
coroutine procedure could not be declared as a local procedure, so the
example I gave was technically incorrect. However, uplevel access to
global variables presents much the same problem.

One thought I had was to just set the static link of the new process to
the frame on the top of the stack of the calling process, with the
dynamic link set to NIL. This would allow uplevel variable access
(determined via traversal of static links), but exitting the frame of
the new process would not reactivate any other frame. Of course, such a
setup would need to trap when a process's initial frame exits. Any
problem is to do with the stack listener interface I'm using - I don't
want multiple stack events generated when only one should be.

Which leads me to another question: according to my Modula-2
documentation, a coroutine cannot exit normally, but must TRANSFER to a
specific coroutine. I assume this is to avoid the dynamic link problem
mentioned above. If so, when does the stack for a coroutine get
disposed? Or does this need to be performed explicitly by the
programmer? I'm using Java threads to handle coroutines and I'd prefer
to kill them off internally when I know it is safe, rather than leave it
up to the programmer.

Quote:

> I agree with what Andreas says. In addition, as a general point you need
> THREE areas of storage:

> i)      Global storage for variables declared in definition modules or
> outside any procedures. On a classical DOS system this would be
> immediately above the code, with the size fixed at compile time.

> ii)     A global heap, common to all threads. This will typically have
> control of the free memory between static memory (i) and the stack (iii).

> iii)    A stack for the main thread/coroutine. Stacks for other coroutines
> will be allocated from (i) or (ii). On a classical DOS system this would
> be at the top of available memory and grow down.

I've got something similar to the above. However, instead of a dedicated
global storage area, static/global variables are contained in a dummy
stack frame that represents the runtime system, which then calls the
main module coroutine.  I found that this simplified the variable access
code (although it may present other problems?).

Quote:
> Bear in mind (a) that Modula-2 coroutines are non-preemptive and (b) that
> Modula-2 was designed to use linked stack frames rather than a display
> register. I've used a compiler with a display register (actually one per
> module if I recall correctly) and it caused a great deal of hassle since
> switching coroutines invalidated the display: the result was that it was
> unsafe to use WITH or up-level addressing in a block which also contained
> a TRANSFER().

I'm aiming on allowing safe, multi-threading interpretation. Actually,
I'm hoping to develop a process abstraction that should allow even local
procedures to act as processes, and implementing coroutines as a
restricted case of that. The reason for this is that my Modula-2
interpreter may be extended to cover other languages as well, so I'm
abstracting out as much as I can.

Quote:
> Please keep us informed how you get on, sounds interesting. Are you
> writing a true interpreter or a compiler to produce Java bytecodes?

A true interpreter, although subject to a number of restrictions to
enforce more rigorous type safety than Modula-2 allows.

Currently it is only text-based (see example debug output below), but
I'm (slowly) making it graphical using Java's Swing set. Trouble is,
there's too much information to display graphically. Do you display a
stack showing the value of every variable, including the contents of
large arrays? Do you explicitly draw a link between a pointer and the
address it dereferences, and if so how do you avoid screen clutter? etc.
Do you display data structures just on the stack, or is it possible to
recognize that some variables represent linked lists or binary trees
(for example)? I still attempting to narrow down the visual depiction of
the data at the moment...

Producing byte-codes is left as an exercise for the reader - it
shouldn't be too hard, but I have higher priorities at the moment. I'm
developing this Modula-2 interpeter in my spare time, which is
decreasing rapidly at the moment. :-(

Cheers,
Geoff

Example Code:
=============

MODULE Bar;

  IMPORT SYSTEM;

  PROCEDURE Swap(VAR x, y: INTEGER);
    VAR temp: INTEGER;
  BEGIN
    temp := y;
    y := x;
    x := temp;
  END Swap;

  PROCEDURE Factorial(n: INTEGER): INTEGER;
  BEGIN
    IF n > 0 THEN
      RETURN n * Factorial(n-1);
    ELSE
      RETURN 1;
    END; (* if *)
  END Factorial;

  VAR n: INTEGER;
      v: RECORD i,j: INTEGER END;
      p,q: POINTER TO INTEGER;

BEGIN (* Bar *)
  NEW(p);
  q := p;
  p^ := 5;
  p := SYSTEM.ADR(v.i);
  v.i := 7;
  q := NIL;             (* heap block now lost *)
  n := Factorial(5);
  Swap(n,v.i);
  n := q^;              (* should cause an error *)
END Bar.

Example Output:
===============
## creating stack frame for block "$runtime$"
## creating static bindings for block "Bar"
(Interpret) block = "$runtime$", #statements = 0
## creating stack frame for block "Bar"
(Interpret) block = "Bar", #statements = 9
(Interpret) statement = Statement.ProcedureCall at [27,3]
## creating stack frame for block "NEW"
## formal "ptr" is a reference to "p"
(NEW) allocating type INTEGER, size = 4

1048576


## destroying stack frame for block "NEW"
(Interpret) statement = Statement.Assignment at [28,3]

(Interpret) statement = Statement.Assignment at [29,3]

Changed value of p^ to 5
Changed value of q^ to 5
(Interpret) statement = Statement.Assignment at [30,3]
## creating stack frame for block "ADR"
## formal "v" is a reference to "v.i"
## destroying stack frame for block "ADR"
Changed value of p to adr[v.i]
(Interpret) statement = Statement.Assignment at [31,3]
Changed value of v.i to 7
Changed value of p^ to 7
(Interpret) statement = Statement.Assignment at [32,3]
Changed value of q to NIL

(Interpret) statement = Statement.Assignment at [33,3]
## creating stack frame for block "Factorial"
## formal "n" gets value 5
(Interpret) block = "Factorial", #statements = 1
(Interpret) statement = Statement.IF at [15,5]
(Interpret) statement = Statement.RETURN at [16,7]
## creating stack frame for block "Factorial"
## formal "n" gets value 4
(Interpret) block = "Factorial", #statements = 1
(Interpret) statement = Statement.IF at [15,5]
(Interpret) statement = Statement.RETURN at [16,7]
## creating stack frame for block "Factorial"
## formal "n" gets value 3
(Interpret) block = "Factorial", #statements = 1
(Interpret) statement = Statement.IF at [15,5]
(Interpret) statement = Statement.RETURN at [16,7]
## creating stack frame for block "Factorial"
## formal "n" gets value 2 (Interpret) block = "Factorial", #statements
= 1
(Interpret) statement = Statement.IF at [15,5]
(Interpret) statement = Statement.RETURN at [16,7]
## creating stack frame for block "Factorial"
## formal "n" gets value 1
(Interpret) block = "Factorial", #statements = 1
(Interpret) statement = Statement.IF at [15,5]
(Interpret) statement = Statement.RETURN at [16,7]
## creating stack frame for block "Factorial"
## formal "n" gets value 0
(Interpret) block = "Factorial", #statements = 1
(Interpret) statement = Statement.IF at [15,5]
(Interpret) statement = Statement.RETURN at [18,7]
## destroying stack frame for block "Factorial"
## destroying stack frame for block "Factorial"
## destroying stack frame for block "Factorial"
## destroying stack frame for block "Factorial"
## destroying stack frame for block "Factorial"
## destroying stack frame for block "Factorial"
Changed value of n to 120
(Interpret) statement = Statement.ProcedureCall at [34,3]
## creating stack frame for block "Swap"
## formal "x" is a reference to "n"
## formal "y" is a reference to "v.i"
## creating binding for local variable "temp"
(Interpret) block = "Swap", #statements = 3
(Interpret) statement = Statement.Assignment at [8,5]
Changed value of temp to 7
(Interpret) statement = Statement.Assignment at [9,5]
Changed value of v.i to 120
Changed value of p^ to 120
Changed value of y to 120
(Interpret) statement = Statement.Assignment at [10,5]
Changed value of n to 7
Changed value of x to 7
## destroying stack frame for block "Swap"
(Interpret) statement = Statement.Assignment at [35,3]
*** Execution error at line 35 ***
    Null pointer dereference



Tue, 25 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?

Quote:


> > SYSTEM.NEWPROCESS expects a procedure parameter of type PROC and this
> > must not be a local procedure. Thus you don't have the problem of
> > static links across stacks in Modula-2.

> Actually, I remembered after I posted the original message that the
> coroutine procedure could not be declared as a local procedure, so the
> example I gave was technically incorrect. However, uplevel access to
> global variables presents much the same problem.

Global variables do not need to be put onto stack and consequently
you do not need static links to access them. They exist just once.
Static links are only needed for access of outer variables on stack
that may exist in multiple incarnations.

Quote:
> Which leads me to another question: according to my Modula-2
> documentation, a coroutine cannot exit normally, but must TRANSFER to a
> specific coroutine.

This is correct.

Quote:
> I assume this is to avoid the dynamic link problem
> mentioned above.

It is simply for the reason that on termination of a coroutine we have
no idea where to continue.

Quote:
> If so, when does the stack for a coroutine get disposed?
> Or does this need to be performed explicitly by the
> programmer?

Yes!

Quote:
> I'm using Java threads to handle coroutines and I'd prefer
> to kill them off internally when I know it is safe, rather than leave it
> up to the programmer.

I do not see a solution for this. It may be solved in a language with
garbage collection (like Oberon, for example) where you can dispose
the coroutine if there are no references on it.

Taking threads as a replacement for coroutines is dangerous
because coroutines have different semantics. While opening multiple
control flows, they are guaranteed to not process in parallel, i.e. there
is only one coroutine active at any time. This makes synchronisation
fare more easier than in the general case of threads.

The only valid technique in taking threads as implementation
for coroutines is to assure strictly the same semantics by blocking
all threads except one.

Andreas.

--
Andreas Borchert, Universitaet Ulm, SAI, Helmholtzstr. 18, 89069 Ulm,  Germany

WWW:    http://www.mathematik.uni-ulm.de/sai/borchert/



Tue, 25 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?
G'day,

Quote:

> Taking threads as a replacement for coroutines is dangerous
> because coroutines have different semantics. While opening multiple
> control flows, they are guaranteed to not process in parallel, i.e. there
> is only one coroutine active at any time. This makes synchronisation
> fare more easier than in the general case of threads.

> The only valid technique in taking threads as implementation
> for coroutines is to assure strictly the same semantics by blocking
> all threads except one.

...which is what I will be doing. I see threads/processes as the higher
level abstraction applicable to most languages, so I am going to have
the design reflect this. Coroutines will then be a special, restricted
case of the general process abstraction.

I note that this is the reverse of implementation I see in many Modula-2
compilers, where high-level processes are built via a scheduler sitting
on top of low-level coroutines.

If and when I get it to work, I'll let everyone know :-)

Cheers,
Geoff



Tue, 25 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?

Quote:

> One thought I had was to just set the static link of the new process to
> the frame on the top of the stack of the calling process, with the
> dynamic link set to NIL. This would allow uplevel variable access
> (determined via traversal of static links), but exitting the frame of
> the new process would not reactivate any other frame. Of course, such a
> setup would need to trap when a process's initial frame exits. Any
> problem is to do with the stack listener interface I'm using - I don't
> want multiple stack events generated when only one should be.

I'm not really a compiler writer but I've done a lot of language support
and (obviously) M2 development. I don't think what you're saying is right:
it seems to me that you are making provision for a child process to access
local (as distinct from global) variables of its parent which doesn't make
sense when you allow that the code of each is a top-level PROC i.e. on
entry each has a clean stack. Global/static variables are shared and their
locations will generally be known at compile-time, stacks are private.

Quote:
> Which leads me to another question: according to my Modula-2
> documentation, a coroutine cannot exit normally, but must TRANSFER to a
> specific coroutine.

A coroutine is effectively a non-preemptive thread, it normally contains a
sequence of operations similar to

BEGIN                           <--- Initial control enters here
  WHILE TRUE
    ...
    TRANSFER                    ---> Control exits here
                                <--- Control returns here, state restored
  END
END

i.e. it runs until the main program terminates. I can't remember the exact
semantics if control falls off the end (and I tend to go by PIM anyway
since that's what the tools I use conform to and the current ISO standard
may differ)...

Quote:
> I assume this is to avoid the dynamic link problem
> mentioned above. If so, when does the stack for a coroutine get
> disposed? Or does this need to be performed explicitly by the
> programmer? I'm using Java threads to handle coroutines and I'd prefer
> to kill them off internally when I know it is safe, rather than leave it
> up to the programmer.

...but at /that/ point the stack and any other local storage representing
the coroutine may be deallocated (if on the heap) or reused.

Quote:
> I've got something similar to the above. However, instead of a dedicated
> global storage area, static/global variables are contained in a dummy
> stack frame that represents the runtime system, which then calls the
> main module coroutine.  I found that this simplified the variable access
> code (although it may present other problems?).

Sounds reasonable, but remember that it is /only/ this that is upwardly
accessible from the real stacks, and also that the heap state will be
stored in this to make sure that the heap is globally accessible.

Quote:
> I'm aiming on allowing safe, multi-threading interpretation. Actually,
> I'm hoping to develop a process abstraction that should allow even local
> procedures to act as processes, and implementing coroutines as a
> restricted case of that. The reason for this is that my Modula-2
> interpreter may be extended to cover other languages as well, so I'm
> abstracting out as much as I can.

Frankly, I wouldn't do this because it could end up with your doing a
constant juggling act working out what goes onto a stack and what has to
be allocated in heap space (or even, heaven forfend, transferred there
on-the-fly). You could obviously simplify things if you specified that a
parent process could not be terminated whilst any child were still running
but it would still be tricky.

Quote:
> A true interpreter, although subject to a number of restrictions to
> enforce more rigorous type safety than Modula-2 allows.

Sounds fascinating, please keep us informed :-)

-- Mark Morgan Lloyd

--
-- [Opinions above are the author's, not those of his employers or
colleagues]
--
-- ** Internet feed may be unreliable- please cc anything important by
email **



Wed, 26 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?

Quote:

> ...which is what I will be doing. I see threads/processes as the higher
> level abstraction applicable to most languages, so I am going to have
> the design reflect this. Coroutines will then be a special, restricted
> case of the general process abstraction.

> I note that this is the reverse of implementation I see in many Modula-2
> compilers, where high-level processes are built via a scheduler sitting
> on top of low-level coroutines.

This all depends on what lower-level facilities are available. Bear in
mind that M2 was designed as a systems-programming language and didn't
assume that a multitasking operating system was present. It's not
difficult to implement a coroutine mechanism on most architectures, in
fact this is a major component of the portable microkernel I use. On top
of the coroutines it's not difficult to put a preemptive kernel, I'd
stress that I'm a heretic who believes that preemption and scheduling are
kernel activities which should not be included in the microkernel... I'm
also a guy who can debug this sort of thing with a logic analyser.

If anything is arse-backwards it's Windows NT, where a thread can be
marked non-preemptive (and becomes a fiber in MS terminology) rather than
vice-versa.

-- Mark Morgan Lloyd

--
-- [Opinions above are the author's, not those of his employers or
colleagues]
--
-- ** Internet feed may be unreliable- please cc anything important by
email **



Wed, 26 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?
Mark:

What are you using (e.g., 'microkernel') to do your coroutines
and pre-emption support?  I have been using M2 (an implementation
that supports coroutines and iotransfer) for some time, and have
been continually looking for a 32-bit implementation, on x86
CPUs.

-Mike



Fri, 28 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?

Quote:
> What are you using (e.g., 'microkernel') to do your coroutines
> and pre-emption support?  I have been using M2 (an implementation
> that supports coroutines and iotransfer) for some time, and have
> been continually looking for a 32-bit implementation, on x86
> CPUs.

I'm afraid it's our own proprietary code, about ten years old. It's 16-bit
and non-preemptive but runs on bare-metal Z80 and bare-metal '386
protected mode as well as a PC. It works on the basis of a main process
that executes an agent procedure on a round-robin basis, each agent
decides whether it's worth calling SwitchTo() hence TRANSFER to a child
process. The child runs until it either explicitly calls Yield to release
the CPU or calls something else that does (e.g. data transfer to a full
queue).

On a Z80 or PC process switching is implemented as TRANSFER, on a
bare-metal '386 TRANSFER-TRANSFER is replaced by intersegment CALL-RETURN
through a TSS. There are some areas with which I am less than happy (e.g.
each time a timer is checked involves a process switch since it's done in
the context of the process that called Wait(), but I'm still typically
getting 1000 loops round the main process per second.

Making this preemptive would not be particularly difficult, I'd just have
to have code hooked onto the timer interrupt which was executed in the
context of the current child process and TRANSFERred or RETed back to the
main process which would then decide what to execute next.

-- Mark Morgan Lloyd

--
-- [Opinions above are the author's, not those of his employers or
colleagues]
--
-- ** Internet feed may be unreliable- please cc anything important by
email **



Fri, 28 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?

Quote:

> > What are you using (e.g., 'microkernel') to do your coroutines
> > and pre-emption support?  I have been using M2 (an implementation
> > that supports coroutines and iotransfer) for some time, and have
> > been continually looking for a 32-bit implementation, on x86
> > CPUs.

> I'm afraid it's our own proprietary code, about ten years old. It's 16-bit
> and non-preemptive but runs on bare-metal Z80 and bare-metal '386
> protected mode as well as a PC. It works on the basis of a main process
> that executes an agent procedure on a round-robin basis, each agent
> decides whether it's worth calling SwitchTo() hence TRANSFER to a child
> process. The child runs until it either explicitly calls Yield to release
> the CPU or calls something else that does (e.g. data transfer to a full
> queue).

> On a Z80 or PC process switching is implemented as TRANSFER, on a
> bare-metal '386 TRANSFER-TRANSFER is replaced by intersegment CALL-RETURN
> through a TSS. There are some areas with which I am less than happy (e.g.
> each time a timer is checked involves a process switch since it's done in
> the context of the process that called Wait(), but I'm still typically
> getting 1000 loops round the main process per second.

> Making this preemptive would not be particularly difficult, I'd just have
> to have code hooked onto the timer interrupt which was executed in the
> context of the current child process and TRANSFERred or RETed back to the
> main process which would then decide what to execute next.

If it uses the FPU for floating point you need some additional logic to save
the FPU stack & context but it is possible to program a preemptive
multitasking M2 application.
For a while we used TS OS/2 M2 compiler in multithreaded mode for the same
job.
(but sadly it is a 16bit compiler and distinctly long in the tooth)

Regards,
Martin Brown

- Show quoted text -

Quote:

> -- Mark Morgan Lloyd

> --
> -- [Opinions above are the author's, not those of his employers or
> colleagues]
> --
> -- ** Internet feed may be unreliable- please cc anything important by
> email **



Sat, 29 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?
On Mon, 12 Apr 1999 08:55:26 -0400, Michael McGaw

Quote:

>Mark:

>What are you using (e.g., 'microkernel') to do your coroutines
>and pre-emption support?  I have been using M2 (an implementation
>that supports coroutines and iotransfer) for some time, and have
>been continually looking for a 32-bit implementation, on x86
>CPUs.

>-Mike

XDS is 32-bit implementation for x86 that supports coroutines. One of
our customers has implemented a small proprietary kernel as a
low-level layer of XDS run-time library. They run it on a 386EX that
controls a DSP board. Email me if you need more details and/or
reference from that company.

Dmitry Leskov
----------------------------------------------------------
Dmitry V. Leskov     Phone     : +7 3832 39 78 24 (ext. 14)

JSC XDS
P.O. Box 415         Phone/fax : +7 3832 39 78 24

630090 Russia        Web       : http://www.xds.ru/



Sat, 29 Sep 2001 03:00:00 GMT  
 Data sharing using COROUTINE?

Quote:

>   The Object Oriented Modula-2 proposal (standard?) added the procedure
> COROUTINEDONE to the COROUTINES module, which is supposed to let the
> garbage collector know that the coroutine will no longer be transferred
> to.  But as you say, this presumes that the implementation provides
> garbage collection, and I don't know of any Modula-2 system that has
> implemented this yet.

I am not familiar with the Object Oriented Modula-2 proposal/standard
but a procedure COROUTINEDONE does not seem useful to me. IMHO a
coroutine should be subject to garbage collection if there is no
reference to it. I am using this technique for Ulm's Oberon System
that supports coroutines (and a garbage collector).

In practice, we have a task manager and usually the task manager is
the only module having the coroutine pointers. By calling Tasks.Terminate,
a coroutine can terminate itself and the task manager will assign NIL
to its coroutine pointer and resume some other coroutine. Later, the
garbage collection is free to cleanup the now unused coroutine stack.

More about it may be found at
   http://www.mathematik.uni-ulm.de/oberon/0.5/lib/man/Tasks.html
   http://www.mathematik.uni-ulm.de/oberon/0.5/articles/coroutines.html

Another problem with Modula-2's NEWPROCESS is that the stack area
is to be supplied by the caller making it impossible to support
growing stacks.

Andreas.

--
Andreas Borchert, Universitaet Ulm, SAI, Helmholtzstr. 18, 89069 Ulm,  Germany

WWW:    http://www.mathematik.uni-ulm.de/sai/borchert/



Mon, 01 Oct 2001 03:00:00 GMT  
 Data sharing using COROUTINE?


Quote:

>   The Object Oriented Modula-2 proposal (standard?) added the procedure
> COROUTINEDONE to the COROUTINES module, which is supposed to let the
> garbage collector know that the coroutine will no longer be transferred
> to.  But as you say, this presumes that the implementation provides
> garbage collection, and I don't know of any Modula-2 system that has
> implemented this yet.

Garbage collection is also required to fully implement the ISO standard
for Object Oriented Modula-2. The p1 compiler for the Mac has a fuull
ISO implementation.

Rick

--
Rick Sutcliffe
Trinity Western University (Not speaking officially)



Mon, 01 Oct 2001 03:00:00 GMT  
 
 [ 19 post ]  Go to page: [1] [2]

 Relevant Pages 

1. multi-process shared data and thread private data

2. VAST 4.5 - ODBC Calls Hang Using Abt Coroutine Calls

3. Q: Acquiring data using two E series devices connected by RTSI and streaming data to disk

4. Using file data transparently as internal data?

5. using NNs for data mining/data analysis

6. Data sharing

7. Shared Memory, Data Compression Documentation Questions

8. Data and Executables sharing directory

9. Shared Modules and Data

10. Confused about sharing data remotely...

11. How to share data between applications.

12. AS/400 shared folders and data queues

 

 
Powered by phpBB® Forum Software