www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - continue in catch block? seperate interaction with widgets and work flow

reply davidl <davidl 126.com> writes:
here we consider a work flow in form 1

//code block 1
...
//feed back to form 1's widgets
...
//code block 2
...
//feed back to form 1's widgets
...

now another form, form 2's code with the same structure

//code block 1
...
//feed back to form 2's widgets
...
//code block 2
...
//feed back to form 2's widgets
...

these two funcs meet one problem , if i want to call form2's func in form1  
the feedback info wouldn't be shown in form1.
and also if i want to call form1's func in form2 the feedback info  
wouldn't be shown.

solution :
i would set up two feedback "server"s for both form1 and form2
form1 now would be:
//code block 1
...
//feedback info ----> "call" server1 to show. but we can't have a call  
directly , we need to signal the operation sysmem first, then let the os  
call our handle func
...
//code block 2
...
//feedback info ----> "call" feedback displayer  again
...

if we send the same syntax feedback info , and the displayer can  
understand that info, then we can have form2's info get shown in form1  
when form1 call form2's method


i suggest a possible solution to this
now we consider following:
try
{
}
catch
{
}

what we need is after handling the exception we need to back to the exact  
point where the exception is raised. since we get our feedback info  
handled in the catch block, but we need to go back when that display done.  
so if continue keyword is possible in catch block ? that would be nice to  
handle the problem i meet.

and if we can call that as action handler , would be nicer.
actionbegin
{
}

actionhandle(action class)
{
	switch (typeof(action))
	{	
		ActionClass1 : writefln(action.Message);
		ActionClass2 : writefln(action.message);
		...
	}
}






-- 
使用 Opera 革命性的电子邮件客户程序: http://www.opera.com/mail/
Oct 19 2006
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
davidl wrote:
 
 here we consider a work flow in form 1
 
 //code block 1
 ...
 //feed back to form 1's widgets
 ...
 //code block 2
 ...
 //feed back to form 1's widgets
 ...
 [snip]

I don't really understand the problem you're trying to describe, but this sentence:
 what we need is after handling the exception we need to back to the 
 exact point where the exception is raised. 

sounds kind of similar to generators & coroutines for which the keyword "yield" is often used. "Green threads" is another related term. You yield back to some controlling process but your functions state is preserved and you can get back there later. Also I think I've seen it described somewhere as generalizing the function call stack into a "function call tree". Some people seem to be crazy about that stuff lately, but I haven't yet really been able to grok what is so great about it. It's supposed to simplify things, but all the I've seen just look harder to understand than the "regular way" to me. Well the generators used to implement iterators in Python make sense to me. Supposedly it's very good for games somehow, though: http://www.eve-online.com/faq/faq_07.asp (look for "stackless") http://harkal.sylphis3d.com/2005/08/10/multithreaded-game-scripting-with-stackless-python/ --bb
Oct 19 2006
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Bill Baxter wrote:

 sounds kind of similar to generators & coroutines for which the keyword
 "yield" is often used.  "Green threads" is another related term.  You
 yield back to some controlling process but your functions state is
 preserved and you can get back there later.  Also I think I've seen it
 described somewhere as generalizing the function call stack into a
 "function call tree".
 
 Some people seem to be crazy about that stuff lately, but I haven't yet
 really been able to grok what is so great about it.  It's supposed to
 simplify things, but all the I've seen just look harder to understand
 than the "regular way" to me.  Well the generators used to implement
 iterators in Python make sense to me.
 
 Supposedly it's very good for games somehow, though:
 http://www.eve-online.com/faq/faq_07.asp (look for "stackless")
 http://harkal.sylphis3d.com/2005/08/10/multithreaded-game-scripting-with-stackless-python/
 
 
 --bb

Disclaimer: Big fan of both Python, Stackless, and this sort of stuff in general. May be just a *wee* bit biased :P *ahem* There are many ways in which coroutines / green threads / generators / tasklets / etc. can make life easier. Here's a few I can think of off the top of my head: 1. State machines. State machines are where you have something like this: void update() { switch( this.currentState ) { case STATE_1: doOneThing(); currentState = STATE_2; break; case STATE_2: doAnotherThing(); currentState = STATE_3; break; case STATE_3: if( timeSpentWaiting >= 1*second ) currentState = STATE_4; break; case STATE_4: doOneLastThing(); currentState = DEAD; break; } } This is a pattern used in games, and any sort of incremental processing. The reason you do this is that you're trying to describe a process, but you need to break off and do other things at the same time. For example, if you're simulating something and you have a million of these buggers, you can't exactly run each one to completion all in one go. However, with coroutines, the above becomes this: void update() { doOneThing(); doAnotherThing(); wait( 1*second ); doOneLastThing(); die(); } Because you can suspend execution of the function, and then resume it later, writing state machines becomes trivial. 2. Pipelines Imagine you have a pipeline of some description. Maybe it's an image processing chain where each part of the pipeline streams pixels in from the previous one, modifies them, and then streams them out to the next in the pipeline. There are a few ways you can do this. You can have each component as a separate function, with an overseeing controller: { foreach( x, y, pixel ; src_image ) { foreach( p ; processors ) pixel = p(pixel); dst_image[x,y] = pixel; } } But then you have a problem with maintaining state with your processors. You could have each processor explicitly pull data from the previous one, or explicitly push data to the next one, but then you're forced to add control logic to the processors where it, frankly, doesn't belong. With coroutines and channels, you can write the components like so: void invert(Channel input_channel, Channel output_channel) { while( input_channel.available && input_channel.connected && output_channel.connected ) { auto pixel = input_channel.receive(); pixel.r = 1.0 - pixel.r; pixel.g = 1.0 - pixel.g; pixel.b = 1.0 - pixel.b; output_channel.send(pixel); } } Which functions pretty much exactly like UNIX pipes. The entire pipeline is just wired together out of simple building blocks, and when either the first runs out or the last breaks off early, the whole thing folds up nice and neat. Plus, the code is brain-dead simple :) 3. Concurrency Another nice feature is that coroutines allow you to do multithreading without ever having to worry about locks or synchronising. Basically, only one coroutine can be running at a time (on a single-core machine, anyway). SENDING a message to another coroutine sleeps the sender and wakes the receiver, which gives you a simple, deterministic way to work out how and when coroutines transfer control. I've seen MUD servers written on coroutines that are mind-bogglingly simple. They LOOK like linear code, they work like linear code, but it jumps around and acts like multithreaded code. It's quite amazing to see :) 4. Generators Finally, a somewhat mundane (although just as powerful) feature that coroutines and their ilk give you are generators/iterators. These are the ones that use "yield"; they allow you to transfer control AND information back to the caller. I'm sure you can find many examples of this easily enough; just go look at Python code. *gets off soap-box* Basically, coroutines are amazingly powerful; they let you write simple, elegant code that looks like a dog's breakfast when written out to accommodate "normal" function call semantics. If you are serious about learning them, the best thing to do is to grab Stackless Python, and play around with the MUD example program. Write a little program full of communicating agents. Then go and try to write it in D. You'll be amazed at how constricted it feels to lose them :) -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Oct 19 2006
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Daniel Keep wrote:
 
 Bill Baxter wrote:
 
 sounds kind of similar to generators & coroutines for which the keyword
 "yield" is often used.  "Green threads" is another related term.
 [...]

 --bb

Disclaimer: Big fan of both Python, Stackless, and this sort of stuff in general. May be just a *wee* bit biased :P *ahem* There are many ways in which coroutines / green threads / generators / tasklets / etc. can make life easier. Here's a few I can think of off the top of my head:

Thanks Daniel for the excellent explanation. All that does make sense to me now.
 1. State machines.

I had heard "state machines" were a good use before, somehow the explanation I read didn't make sense to me. Yours did.
 2. Pipelines
 
 With coroutines and channels, you can write the components like so:
 
 void invert(Channel input_channel, Channel output_channel)
 {
     while( input_channel.available
         && input_channel.connected
         && output_channel.connected )
     {
         auto pixel = input_channel.receive();
         pixel.r = 1.0 - pixel.r;
         pixel.g = 1.0 - pixel.g;
         pixel.b = 1.0 - pixel.b;
         output_channel.send(pixel);
     }
 }
 

So I take it that allows you to write code like: image.invert().grayscale().auto_contrast().threshold() Where each pixel is processed one-by-one rather than creating big memory-hogging tmp images as the output for every stage. That is nice. I remember searching for some way to do this kind of stream processing back in my early days with C and being surprised that there wasn't. Especially surprising since like you say Unix is all about pipes and chaining things together, and Unix and C go hand in hand.
 
 3. Concurrency
 

I can see it makes code simpler, but "single threaded" concurrency seems kinda a bad direction to be heading when 64 core processors are right on the horizon.
 
 4. Generators
 

This one made sense to me before. So is there any reason D couldn't work with coroutines? It just needs to manage the stack in a slightly more tricky way, basically, right? --bb
Oct 19 2006