Thread overview
Function Pointer Not Working
6 days ago
Marcone
6 days ago
Marcone
6 days ago
Kagamin
6 days ago
Marcone
6 days ago
Marcone
6 days ago
// Function threadingw()
void threadingw(HWND hwn, void delegate() fun) nothrow {
	try {
		// Function _fun()
		extern(Windows)
		uint _fun(void * arg){
			(*(cast(void delegate()*) arg))(); // Do not show "Hello World!" :(
			return 0;
		}
		CreateThread(null, 0, &_fun, &fun, 0, null);
	} catch(Throwable){}
}

void main(){
	null.threadingw({writeln("Hello World!");});

}
6 days ago
On Thursday, 19 November 2020 at 04:23:13 UTC, Marcone wrote:
> // Function threadingw()
> void threadingw(HWND hwn, void delegate() fun) nothrow {
> 	try {
> 		// Function _fun()
> 		extern(Windows)
> 		uint _fun(void * arg){
> 			(*(cast(void delegate()*) arg))(); // Do not show "Hello World!" :(
> 			return 0;
> 		}
> 		CreateThread(null, 0, &_fun, &fun, 0, null);
> 	} catch(Throwable){}
> }
>
> void main(){
> 	null.threadingw({writeln("Hello World!");});
>
> }

A delegate is a "fat" pointer (function pointer + context), so it can't fit in a void*.

You could do something like the following to "uncurry" the delegate and extract its context to a void* and a regular function, which can then combine the void* given to it later to call the original delegate:

import std.traits;

auto uncurryDelegate(alias anchor, alias target)()
{
	alias Args = Parameters!target;
	alias R = ReturnType!target;

	alias ContextPtr = void*;
	alias Dg = typeof(&target);

	union Delegate
	{
		Dg dg;
		struct
		{
			void* ptr;
			void* funcptr;
		}
	}

	auto dg = Delegate(&target);
	__gshared void* funcptr; // Will always be the same for this instantiation
	funcptr = (&target).funcptr;

	static struct Result
	{
		R function(ContextPtr ptr, Args args) fun;
		ContextPtr context;
	}

	static R fun(ContextPtr ptr, Args args)
	{
		Delegate dg;
		dg.funcptr = funcptr;
		dg.ptr = ptr;
		return dg.dg(args);
	}
	return Result(&fun, dg.ptr);
}

auto uncurryDelegate(alias target)()
{
	return uncurryDelegate!(target, target);
}

unittest
{
	int fun(int i)
	{
		return i + 1;
	}
	auto r = uncurryDelegate!fun;
	assert(r.fun(r.context, 2) == 3);
}

unittest
{
	struct S
	{
		int i;
		int fun(int j)
		{
			return i + j;
		}

		auto funUncurried() { return uncurryDelegate!(i, fun); }
	}
	auto s = S(2);
	auto r = s.funUncurried();
	assert(r.fun(r.context, 3) == 5);
}

Sadly you can't write `static immutable void* funcptr = (&target).funcptr;`, because the compiler tries to evaluate &target first.

Alternatively you could do this (not recommended): https://stackoverflow.com/a/8656294/21501
6 days ago
Solved replacing this line:

CreateThread(null, 0, &_fun, &fun, 0, null);

to this code:
task!({CreateThread(null, 0, &_fun, &fun, 0, null);}).executeInNewThread();
6 days ago
The delegate is stored on the stack of the calling thread, the created thread loads it from there, but the calling thread doesn't wait for that and clobbers the stack right away. If you were lucky your code would crash.
6 days ago
On Thursday, 19 November 2020 at 15:51:09 UTC, Kagamin wrote:
> The delegate is stored on the stack of the calling thread, the created thread loads it from there, but the calling thread doesn't wait for that and clobbers the stack right away. If you were lucky your code would crash.

The thread that I do wait ultil function is finished. Using a while with 3 seconds to verify if thread id is in running list, and break if not finishing owner thread.
6 days ago
I will wait with this code.
WaitForSingleObject(threading, INFINITE);