www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Proposal: Alias more powerful concurrency, and more powerful manipulation of try block

reply DavidL <Davidl 126.com> writes:
Consider the following:
here I propose two syntax, firstly scope(char[] ScopeName){} ,this syntax  
name those unnamed scope,
and it also make alias for named scope.

void func(){} <-- this a named scope
for(;;){}  <-- here is a anonymous scope

scope("myscope"){ void func(){} } <--- we set up an alias "myscope" for  
func
scope("forscope"){for(;;){}}  <--- we name the anonymous scope with  
scope("forscope")
for(;;)scope("forscope"){} should do exactly the same as  
scope("forscope"){for(;;){}}

ok, now we come to the second syntax proposal.
void func()
{
    int symbol;
}
void anotherfunc()
{
    alias func.symbol localsymbol;  // here i tend to introduce the symbol  
for local stack simulation for concurrency manipulation.
}


a little bit more complicated situation

void func()
{
   int symbol;
   for(int i;i<200;i++) scope("myscope"){

   }
}

void anotherfunc()
{
   alias func.myscope.i funci; //  now if we get the same EBP of execution  
of func, the compiler would ensure us the &func.myscope.i should be the  
same as &funci. If func.myscope.i is optimized to registers, the compiler  
would ensure funci also access the value through the register which  
func.myscope.i use.
}


Let's go a little bit further and concern the parameters of a func :

void func(int fancyarg, ...)
{

}

void anotherfunc()
{
   alias func.fancyarg funcparam;
   alias func.__parameter funcelipsisparams;

}

Ok , what's the motivation of proposing such a feature?

consider cheap concurrency:

void func()
{
   int i;
   int j;
   //library yield func
}

the yield is fine, but we lose the opportunity of interacting with func

and consider a classical situation of a signal and handling.
Windows SEH specific(though I think this could also be done on Linux):

char globalchar;
int FilterFunc()
{
   alias func1.flag flag;
   alias func1.p p;
   // i emit the code of making the context the same as func1. The SEH can  
provide us the exact the same context with fucn1
   if (flag>2) // we can do some fancy operation , the code here just mean  
to illustrate the manipulation of the context of func
   {
     return EXCEPTION_EXECUTE_HANDLER;  // really handle the exception in  
our handler block.
   }
   else
   {
     p= &globalchar;
     // call some signal handle func
     return EXCEPTION_CONTINUE_EXECUTION;  // we can continue the execution  
of func , with *p points to globalchar
   }

}

void func()
{
   __try         // original SEH try
   {
     func1;
   }
   // i hope if D could expose some kind of this low level exception  
manipulation to us.
   __ecept(FilterFunc)  //original SEH catch block with calling to filter  
func firstly to determine what to do with the exception.
   {
      // we only come to here with func1.flag > 2

   }
}

void func1()
{
   int flag;
   char *p=cast(char*)0;
   *p=0;			// trigger the exception. The filter func gets run. now we get p  
points to globalchar
   assert(p !is null);
   flag=3;
   p=cast(char*)0;
   *p=0;                 // trigger the exception. The filter func gets  
run. Now the exception really get thrown to the func. func handler gets run
}

The above is useful for creating some complicated obfuscating code of  
preventing someone from debugging :D
Though it's a nice try to give an alternative of current signal & slot by  
using exceptions.









-- 
使用 Opera 革命性的电子邮件客户程序: http://www.opera.com/mail/
Sep 21 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
I could be wrong, but I don't think any of this is even *remotely* possible.

What you're trying to do is access a piece of memory without having
*any* idea where it is.  Consider your SEH example; there is simply no
way for FilterFunc to know where func1.flag is.  Where that variable is
stored depends entirely on what functions got called before it.  Hell,
what if func1 has recursively called itself several times before calling
FilterFunc?  What does the alias mean then?

What's more, look at how the code is structured; you call func1 from
func, and then call into FilterFunc.  But by the time FilterFunc is
called, func1's local state is no longer on the stack; it's more than
likely been replaced by FilterFunc's own local state.

On a side note, I fail to see what this has to do with concurrency.

	-- Daniel
Sep 21 2007
next sibling parent DavidL <Davidl 126.com> writes:
在 Sat, 22 Sep 2007 13:56:26 +0800,Daniel Keep  
<daniel.keep.lists gmail.com> 写道:

 I could be wrong, but I don't think any of this is even *remotely*  
 possible.

 What you're trying to do is access a piece of memory without having
 *any* idea where it is.  Consider your SEH example; there is simply no
 way for FilterFunc to know where func1.flag is.  Where that variable is
 stored depends entirely on what functions got called before it.  Hell,
 what if func1 has recursively called itself several times before calling
 FilterFunc?  What does the alias mean then?

accessing func1.flag is *well* known at least in the implementation of the scope func1. Either it's [EBP-0xC] or something else. It's fixed to the context no matter how the func1 recursively call itself several times. The FilterFunc tries to access to the local vars of current context ( the func1 specific context ). Alias means the compiler en- sure the accessing codegen is exactly the same as the func1. So under the same context and with the memory not corrupted the func can access local vars which are restricted to the scope of func1.
 What's more, look at how the code is structured; you call func1 from
 func, and then call into FilterFunc.  But by the time FilterFunc is
 called, func1's local state is no longer on the stack; it's more than
 likely been replaced by FilterFunc's own local state.

I don't think so, since there's EXCEPTION_CONTINUE_EXECUTION, at least win32 exception won't destroy the stack frame when it tries to execute the FilterFunc.
 On a side note, I fail to see what this has to do with concurrency.

The idea is you can interact with concurrency code without placing specific code to handle such staff.
 	-- Daniel

-- 使用 Opera 革命性的电子邮件客户程序: http://www.opera.com/mail/
Sep 22 2007
prev sibling parent DavidL <davidl 126.com> writes:
Daniel Keep Wrote:

 
 I could be wrong, but I don't think any of this is even *remotely* possible.
 
 What you're trying to do is access a piece of memory without having
 *any* idea where it is.  Consider your SEH example; there is simply no
 way for FilterFunc to know where func1.flag is.  Where that variable is
 stored depends entirely on what functions got called before it.  Hell,
 what if func1 has recursively called itself several times before calling
 FilterFunc?  What does the alias mean then?
 
 What's more, look at how the code is structured; you call func1 from
 func, and then call into FilterFunc.  But by the time FilterFunc is
 called, func1's local state is no longer on the stack; it's more than
 likely been replaced by FilterFunc's own local state.
 
 On a side note, I fail to see what this has to do with concurrency.
 
 	-- Daniel

*p=0; // this would possibly be generated to two lines of asm // the latter one which assign 0 to the target would trigger the // the exception. So for this level continue exception, we need // to make the temp address for accessing *p be updated not // only p itself. following illustrate the problem more clearly: *p=0 could be: mov EAX, [p] mov byte ptr [EAX],0 So we need to update EAX not *p workaround could be reexecute the whole statement again. The infomation could be extracted from the debug build of an app. When an exception occurs. If the handler want to continue the execution , the handler would firstly need to find out the address of the exact begin of the statement address(this case is the address of mov EAX,[p];) After running some correctoin func, we go back to execute the whole statement again. A little bit further: auto myclass= new Class; some one might argue that if an exception presents in the C-tor of a class, the memory is allocated, if you reexecute the whole statement then the block of memory is wasted. But the problem is when a user want the power of manipulating the thrower code, he *should* be well informed what kind of exceptions there might be, so he *should* be on his own for this kind of specific problem.
Sep 22 2007