www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 2159] New: Thread throws window exception upon termination

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2159

           Summary: Thread throws window exception upon termination
           Product: D
           Version: 2.016
          Platform: PC
        OS/Version: Windows
            Status: NEW
          Severity: normal
          Priority: P2
         Component: Phobos
        AssignedTo: bugzilla digitalmars.com
        ReportedBy: bartosz relisoft.com


This is a very simple test case. The thread runs to completion end then throws
an exception:
Error: Win32 Exception

import std.thread;
void main()
{
        int g;
        int run()
        {
                for(int i = 0; i < 1000; ++i)
                        ++g;
                return 0;
        }
        auto t = new Thread(run);
        t.start;
        t.wait;
}


-- 
Jun 21 2008
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2159


torhu yahoo.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |INVALID





I hate to be the one to say this, but there's an important typo in your test
case.

try this diff:
-auto t = new Thread(run);
+auto t = new Thread(&run);

You ended up calling the ctor that takes a size_t instead of the function
pointer one.


-- 
Jun 22 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2159


bartosz relisoft.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
          Component|Phobos                      |DMD
         Resolution|INVALID                     |
            Summary|Thread throws window        |Confusion between function
                   |exception upon termination  |call and C++ style function
                   |                            |address





Then this is an even more serious language-design problem. Run was called
without me using the call syntax. This might be okay for no-argument methods,
but it's a bad idea for non-member functions, as my example illustrates. 


-- 
Jun 22 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2159


bugzilla digitalmars.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|REOPENED                    |RESOLVED
         Resolution|                            |INVALID





This is not a language design problem, it is intended to work this way. The
fact that run() worked as an argument is because run() returns an int and one
of the constructors for Thread takes a size_t.


-- 
Jun 27 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2159


bartosz relisoft.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |





For me there's no doubt that it's a design flaw in the language and I'll try to
explain my reasoning. 

For people coming from C/C++: A function name in C is treated as a function
pointer. It's okay for D to make this syntax illegal. It's not okay to give
this syntax a completely different meaning (function call), expecially if there
are situations where the error is undetectable. I was lucky the the result of
run() was too small for the stack size, otherwise my unit test would run
without a problem. 

Program understanding: How does the compiler know that "run" is a call and not
a variable? Because it has the symbol table. The symbol might be defined
arbitrarily far from the point of use. That's fine for the compiler but not for
the programmer who's reading somebody else's code. Now the reviewer must chase
multiple files in order to figure out if something is a function call or a
variable. You can't really say that it shouldn't matter for the reviewer
whether a given statement is a function call. 

Notice that the analogous method-call syntax is not bad, because it has a
different context. There is always an object involved. Without any knowledge of
the symbol table, the programmer assumes that it's an access to a public data
member. The fact that it expands to a method call is the matter of the object,
whose designer decided to hide this implementation detail. This is very much in
the spirit of object-oriented programming--implementation hiding. But there is
a well-defined owner/encapsulator of implementation details--the object. 

From the abstract point of view, when you allow a symbol to transparently
expand into a function call, you are making a unification. The new abstraction
is a "variable or a function call". What is this abstraction? Do you have a
name for it? If you don't, it's just a hack that saves two keystrokes and makes
the code more obfuscated. Keystroke-saving improvements should not be a design
goal in itself. 

Note that there is an analogous abstration for method calls. It's called a
"property". 

When we discuss this topic in writing, you use the syntax "run()" rather than
"run". That's because you want to be clear that you mean a function call. When
you write a program you also communicate with other programmers. You should be
as clear about the meaning as you are in our discussion. If I were reviewing
somebody else's code I would demand they use the function-call syntax. 


-- 
Jun 28 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2159


bugzilla digitalmars.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |enhancement




-- 
Jun 29 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2159






yes, this is really nasty.

One solution is change the interface of Thread class. But it's not a good
solution.
Because that relies on the higher interface design quality of lib
developers(and it's not necessary in other langs).


should/could be used as a property by property syntax is better.

For this case, the real problem is that "run" in normal sense is not a
"property", but it can be misused in property syntax. 


-- 
Jun 29 2008
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2159






In the meanwhile I found an example of ambiguity. Here’s some sample code
from the documentation of std.algorithm:

inPlace!(writeln)(arr1); // print the array

Why isn't writeln executed on the spot? Are we passing a function of no
arguments as an alias parameter to a template, or are we evaluating the
function and passing its result to the template? Note that here additional
parentheses would change the meaning of code.

inPlace!(writeln())(arr1);


-- 
Jun 30 2008
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=2159







switch writeln to a CTFE able function and that would be a problem. In that
exact cases the alias must be used because it's the only compile-time option.
And then I think it's only 2.0 that allows values as aliases.


-- 
Jun 30 2008