digitalmars.D.learn - make a nothrow call a throwing function
- monarch_dodra (10/10) Feb 07 2013 Is there any way that a nothrow function can call a function that
- Jonathan M Davis (3/16) Feb 07 2013 You can cast the function.
- monarch_dodra (11/32) Feb 07 2013 Smart.
- 1100110 (4/32) Feb 07 2013 scope(failure) has worked for me in the past, but mostly calling C
- Maxim Fomin (14/31) Feb 07 2013 So, you want to call function (which throws) from function marked
- monarch_dodra (5/43) Feb 07 2013 In this particular case, in is an string dup, so it *should* be
- Jonathan M Davis (12/14) Feb 07 2013 I believe that the problem is that the function isn't marked nothrow eve...
- monarch_dodra (33/56) Feb 07 2013 I was though able to get a function pointer, and cast said
- Jonathan M Davis (8/15) Feb 07 2013 Hmmm. I wouldn't have thought that you could get the function pointer at...
- Artur Skawina (4/8) Feb 08 2013 It doesn't affect inlining. (Obviously, that's compiler dependent, but t...
- Jonathan M Davis (8/16) Feb 08 2013 How could it not affect inlining? You're using a pointer to a function i...
- monarch_dodra (22/47) Feb 08 2013 Well, aren't you saying that because usually, function pointers
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/17) Feb 08 2013 function instead
- Artur Skawina (11/28) Feb 08 2013 "&f" is an expression that evaluates to a constant, known at compile tim...
Is there any way that a nothrow function can call a function that throws, but without even trying to catch if an exception is thrown? My use case is a pretty low level nothrow function, that needs to call something that never ever throws, but was not marked as such. I want to avoid the "try/catch/[do nothing|assert]" because I don't want to pay for that. Ideally, i'd really just want to mark my function as nothrow, and have undefined behavior if it *does* throw. Any way to do that?
Feb 07 2013
On Thursday, February 07, 2013 11:06:14 monarch_dodra wrote:Is there any way that a nothrow function can call a function that throws, but without even trying to catch if an exception is thrown? My use case is a pretty low level nothrow function, that needs to call something that never ever throws, but was not marked as such. I want to avoid the "try/catch/[do nothing|assert]" because I don't want to pay for that. Ideally, i'd really just want to mark my function as nothrow, and have undefined behavior if it *does* throw. Any way to do that?You can cast the function. - Jonathan M Davis
Feb 07 2013
On Thursday, 7 February 2013 at 10:55:26 UTC, Jonathan M Davis wrote:On Thursday, February 07, 2013 11:06:14 monarch_dodra wrote:Smart. Unfortunatly, in this case, I'm trying to call "string.dup". It would appear though that (apparently), dup is a property that returns a function pointer, or something. In any case, I can't seem to be able to get its address. Now I feel kind of bad for suggesting banning taking the address of a property function ... I can bypass this with a wrapper function I guess, but at this point, I'd have to bench to see if that is even worth it...Is there any way that a nothrow function can call a function that throws, but without even trying to catch if an exception is thrown? My use case is a pretty low level nothrow function, that needs to call something that never ever throws, but was not marked as such. I want to avoid the "try/catch/[do nothing|assert]" because I don't want to pay for that. Ideally, i'd really just want to mark my function as nothrow, and have undefined behavior if it *does* throw. Any way to do that?You can cast the function. - Jonathan M Davis
Feb 07 2013
On 02/07/2013 05:38 AM, monarch_dodra wrote:On Thursday, 7 February 2013 at 10:55:26 UTC, Jonathan M Davis wrote:scope(failure) has worked for me in the past, but mostly calling C functions from nothrow. You do have to put it at the top of the function, but it's simple and nice.On Thursday, February 07, 2013 11:06:14 monarch_dodra wrote:Smart. Unfortunatly, in this case, I'm trying to call "string.dup". It would appear though that (apparently), dup is a property that returns a function pointer, or something. In any case, I can't seem to be able to get its address. Now I feel kind of bad for suggesting banning taking the address of a property function ... I can bypass this with a wrapper function I guess, but at this point, I'd have to bench to see if that is even worth it...Is there any way that a nothrow function can call a function that throws, but without even trying to catch if an exception is thrown? My use case is a pretty low level nothrow function, that needs to call something that never ever throws, but was not marked as such. I want to avoid the "try/catch/[do nothing|assert]" because I don't want to pay for that. Ideally, i'd really just want to mark my function as nothrow, and have undefined behavior if it *does* throw. Any way to do that?You can cast the function. - Jonathan M Davis
Feb 07 2013
On Thursday, 7 February 2013 at 11:38:29 UTC, monarch_dodra wrote:On Thursday, 7 February 2013 at 10:55:26 UTC, Jonathan M Davis wrote:So, you want to call function (which throws) from function marked as nothrow? It seems to be breaking idea of what nothrow does. You can do this in general by casting (which is preferred way) and by exploiting current holes/misspecified tricks/corner language cases which should be in general avoided. Unfortunately, it appears that you cannot cast in your particular case of array duplication. However there are other ways to break nothrow and you can use them (declaration mismatch, unions, delegates). I think the problem is not absence of ways of doing what you want, but in limitation of casting with respect to some properties of built-in types. By the way, I would not say that dup array property cannot throw exceptions.On Thursday, February 07, 2013 11:06:14 monarch_dodra wrote:Smart. Unfortunatly, in this case, I'm trying to call "string.dup". It would appear though that (apparently), dup is a property that returns a function pointer, or something. In any case, I can't seem to be able to get its address. Now I feel kind of bad for suggesting banning taking the address of a property function ... I can bypass this with a wrapper function I guess, but at this point, I'd have to bench to see if that is even worth it...Any way to do that?You can cast the function. - Jonathan M Davis
Feb 07 2013
On Thursday, 7 February 2013 at 20:46:22 UTC, Maxim Fomin wrote:On Thursday, 7 February 2013 at 11:38:29 UTC, monarch_dodra wrote:In this particular case, in is an string dup, so it *should* be nothrow. Still the final solution has is more problematic than anything, so I'll just try/catch.On Thursday, 7 February 2013 at 10:55:26 UTC, Jonathan M Davis wrote:So, you want to call function (which throws) from function marked as nothrow? It seems to be breaking idea of what nothrow does. You can do this in general by casting (which is preferred way) and by exploiting current holes/misspecified tricks/corner language cases which should be in general avoided. Unfortunately, it appears that you cannot cast in your particular case of array duplication. However there are other ways to break nothrow and you can use them (declaration mismatch, unions, delegates). I think the problem is not absence of ways of doing what you want, but in limitation of casting with respect to some properties of built-in types. By the way, I would not say that dup array property cannot throw exceptions.On Thursday, February 07, 2013 11:06:14 monarch_dodra wrote:Smart. Unfortunatly, in this case, I'm trying to call "string.dup". It would appear though that (apparently), dup is a property that returns a function pointer, or something. In any case, I can't seem to be able to get its address. Now I feel kind of bad for suggesting banning taking the address of a property function ... I can bypass this with a wrapper function I guess, but at this point, I'd have to bench to see if that is even worth it...Any way to do that?You can cast the function. - Jonathan M Davis
Feb 07 2013
On Thursday, February 07, 2013 21:46:21 Maxim Fomin wrote:So, you want to call function (which throws) from function marked as nothrow? It seems to be breaking idea of what nothrow does.I believe that the problem is that the function isn't marked nothrow even though it doesn't throw. He essentially wants to be able to make the compiler treat it as nothrow at the call site (since he can't change the function definition) without any overhead, and I don't think that that's actually possible. The normal way to handle cases where you know that a function won't throw but isn't nothrow is to wrap it in a try block and put an assert(0) statement in the catch block. That does incur some amound of overhead, but I don't know how much. Apparently, monarch_dodra thinks that it's too much for what he's doing though. - Jonathan M Davis
Feb 07 2013
On Thursday, 7 February 2013 at 21:32:28 UTC, Jonathan M Davis wrote:On Thursday, February 07, 2013 21:46:21 Maxim Fomin wrote:I was though able to get a function pointer, and cast said pointer, at compile time (place it an enum). At that point, calling the function via the compile-time known pointer *should* be just as efficient as calling the function directly. I'll need to check the assembly. EG: //---- import std.stdio; void bar() {writeln("bar");} void foo() nothrow { enum barnothrow = cast(void function() nothrow)(&bar); barnothrow(); } void main() {foo();} //---- Yes, writeln actually can throw, so it's a bad example, but a proof. I'd be surprised if there was any run-time overhead (but I could be wrong). In my case though, there is an extra overhead that I can't get a function pointer to dup, so I have to create an intermediary function. Depending on the inlined-ness of things, *that* may or may not incur an overhead.So, you want to call function (which throws) from function marked as nothrow? It seems to be breaking idea of what nothrow does.I believe that the problem is that the function isn't marked nothrow even though it doesn't throw. He essentially wants to be able to make the compiler treat it as nothrow at the call site (since he can't change the function definition) without any overhead, and I don't think that that's actually possible.The normal way to handle cases where you know that a function won't throw but isn't nothrow is to wrap it in a try block and put an assert(0) statement in the catch block. That does incur some amound of overhead, but I don't know how much. Apparently, monarch_dodra thinks that it's too much for what he's doing though. - Jonathan M DavisWell, I don't think it's too much, but wanted to know the alternatives. I like to know my options, and their costs. It costs nothing to ask, and you never know what you'll learn. I think the conclusion I came to though is to bite the bullet, and not worry too about it. Thank you for your answers anyways.
Feb 07 2013
On Thursday, February 07, 2013 23:14:51 monarch_dodra wrote:I was though able to get a function pointer, and cast said pointer, at compile time (place it an enum). At that point, calling the function via the compile-time known pointer *should* be just as efficient as calling the function directly. I'll need to check the assembly.Hmmm. I wouldn't have thought that you could get the function pointer at compiler time. Regardless, you lose any possibility of inlining the function call, which is the main problem AFAIK, though I don't know if they would have been an option in the case of dup anyway.I think the conclusion I came to though is to bite the bullet, and not worry too about it.Well, long term, this should be solved by dup actually being nothrow when it can't throw. - Jonathan M Davis
Feb 07 2013
On 02/08/13 01:33, Jonathan M Davis wrote:Hmmm. I wouldn't have thought that you could get the function pointer at compiler time. Regardless, you lose any possibility of inlining the function call, which is the main problem AFAIK, though I don't know if they would have been an option in the case of dup anyway.It doesn't affect inlining. (Obviously, that's compiler dependent, but there's no reason why it should and indeed does not w/ gdc) artur
Feb 08 2013
On Friday, February 08, 2013 09:30:41 Artur Skawina wrote:On 02/08/13 01:33, Jonathan M Davis wrote:How could it not affect inlining? You're using a pointer to a function instead of the function itself, so it can't be inlined. Do you mean that dup in particular doens't get inlined even when called directly? That's quite possible, but in the general case, using a function pointer rather than calling a function directly risks taking a small efficiency hit due to the fact that the function can no longer be inlined. - Jonathan M DavisHmmm. I wouldn't have thought that you could get the function pointer at compiler time. Regardless, you lose any possibility of inlining the function call, which is the main problem AFAIK, though I don't know if they would have been an option in the case of dup anyway.It doesn't affect inlining. (Obviously, that's compiler dependent, but there's no reason why it should and indeed does not w/ gdc)
Feb 08 2013
On Friday, 8 February 2013 at 09:33:19 UTC, Jonathan M Davis wrote:On Friday, February 08, 2013 09:30:41 Artur Skawina wrote:Well, aren't you saying that because usually, function pointers aren't obtained at compile time? In any case, I also tested it, and the disassemble seems to give the exact same code (inlined, as far as I can tell) for calling via function or function pointer: And a third version, after adding the "nothrow" keyword. Slight changes, but I can't tell if they are "true" changes: That said, when everything is said and done, the try catch version also generates the same inline code But in this case, the compiler has access to the call, so it can *tell* exceptions won't get thrown. Finally, in this last version, which calls dup, we can see the "cast" version takes less intructions that the try/catch version. But at the end of the day, it is a dangerous semantic for not that much gain.On 02/08/13 01:33, Jonathan M Davis wrote:How could it not affect inlining? You're using a pointer to a function instead of the function itself, so it can't be inlined. Do you mean that dup in particular doens't get inlined even when called directly? That's quite possible, but in the general case, using a function pointer rather than calling a function directly risks taking a small efficiency hit due to the fact that the function can no longer be inlined. - Jonathan M DavisHmmm. I wouldn't have thought that you could get the function pointer at compiler time. Regardless, you lose any possibility of inlining the function call, which is the main problem AFAIK, though I don't know if they would have been an option in the case of dup anyway.It doesn't affect inlining. (Obviously, that's compiler dependent, but there's no reason why it should and indeed does not w/ gdc)
Feb 08 2013
On 02/08/2013 01:32 AM, Jonathan M Davis wrote:On Friday, February 08, 2013 09:30:41 Artur Skawina wrote:pointer atOn 02/08/13 01:33, Jonathan M Davis wrote:Hmmm. I wouldn't have thought that you could get the functionfunction insteadHow could it not affect inlining? You're using a pointer to acompiler time. Regardless, you lose any possibility of inlining the function call, which is the main problem AFAIK, though I don't know if they would have been an option in the case of dup anyway.It doesn't affect inlining. (Obviously, that's compiler dependent, but there's no reason why it should and indeed does not w/ gdc)of the function itself, so it can't be inlined.Taking the address of a function ensures that the function exists but it does not preclude inlining the code of that function. Ali
Feb 08 2013
On 02/08/13 10:32, Jonathan M Davis wrote:On Friday, February 08, 2013 09:30:41 Artur Skawina wrote:"&f" is an expression that evaluates to a constant, known at compile time (modulo link-/run-time relocation/offset fixups, but that's irrelevant here). "(&f)()" is trivially recognizable (for the compiler) as equivalent to "f()". Not unlike the "int i; auto j = *&i, k = i;" case where you can expect the compiler to optimize away the address-of and dereferencing, and evaluate the first expression just like the second one.On 02/08/13 01:33, Jonathan M Davis wrote:How could it not affect inlining? You're using a pointer to a function instead of the function itself, so it can't be inlined. Do you mean that dup inHmmm. I wouldn't have thought that you could get the function pointer at compiler time. Regardless, you lose any possibility of inlining the function call, which is the main problem AFAIK, though I don't know if they would have been an option in the case of dup anyway.It doesn't affect inlining. (Obviously, that's compiler dependent, but there's no reason why it should and indeed does not w/ gdc)of the function itself, so it can't be inlined. Do you mean that dup in particular doens't get inlined even when called directly? That's quite possible, but in the general case, using a function pointer rather than calling a function directly risks taking a small efficiency hit due to the fact that the function can no longer be inlined.It makes no difference. I actually checked, because I was wondering if the reinterpret cast wasn't confusing the compiler - it doesn't and inlining happens as it should even with that cast in the mix. artur
Feb 08 2013