shared not working!

Hiemlick Hiemlicker via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jul 3 18:50:24 PDT 2016


On Monday, 4 July 2016 at 01:36:00 UTC, Mike Parker wrote:
> On Sunday, 3 July 2016 at 23:20:35 UTC, Hiemlick Hiemlicker 
> wrote:
>
>>
>> The only difference is that the thread is a windows 
>> CreateThread. I guess D doesn't know about such threads and 
>> hence shared doesn't extend across to them?
>
> The runtime doesn't know about external threads, no. You have 
> to tell it about them with a call to thread_attachThis() [1]. 
> Still, AFAIK, shared variables should not be dependent upon 
> runtime threads. Do you have a minimum working example to share?
>
> [1] https://dlang.org/phobos/core_thread.html#.thread_attachThis



Basically the sExtThread struct, changed __gshared to shared or 
remove.

You can check the and see that the values are correct in the 
thread by writeln(&paused) type of thing(or store address in 
global variable).


import std.stdio, std.datetime, std.algorithm, std.string;
import core.thread, core.sync.mutex, core.atomic;


version (Windows)
{
     import core.sys.windows.windows;

     void makeExecutable(void[] code)
     {
         DWORD old;
         VirtualProtect(code.ptr, code.length, 
PAGE_EXECUTE_READWRITE, &old);
     }
}
else
version (linux)
{
     import core.sys.posix.sys.mman;
     import core.sys.posix.unistd;

     static if (!is(typeof(&mprotect)))
         extern(C) int mprotect(void*, size_t, int);

     void makeExecutable(ubyte[] code)
     {
         auto pageSize = sysconf(_SC_PAGE_SIZE);
         auto address = ((cast(size_t)code.ptr) & ~(pageSize-1));
         int pageCount = (address/pageSize == 
(address+code.length)/pageSize) ? 1 : 2;
         mprotect(cast(void*)address, pageSize * pageCount, 
PROT_READ | PROT_WRITE | PROT_EXEC);
     }
}
else
     static assert(0, "TODO");

// Creates a thunk by creating a function(functionTemplate), 
which the compiler generates code for
// then manipulates the function's code indirectly so the actual 
architecture asm is not required.

// Creates a thunk by creating a function(functionTemplate), 
which the compiler generates code for
// then manipulates the function's code indirectly so the actual 
architecture asm is not required.
R function(A) Delegate2Function(R, A...)(R delegate(A) d)
{
	// Memory placeholders for d.ptr and d.funcptr. Stored per 
template `instance`.
     shared enum size_t TEMPLATE1 = 
cast(size_t)0x01234567_01234567;
     shared enum size_t TEMPLATE2 = 
cast(size_t)0x89ABCDEF_89ABCDEF;
	
	// Thunk callback. This is the function called by Win32, which 
creates the delegate and points it
	// to the desired callback.  It stores the callback this and 
function ptr in TEMPLATE1 & TEMPLATE2 resp.
	extern(Windows) // No good?
     static R functionTemplate(A args)
     {
         R delegate(A) d;
         d.ptr     = cast(typeof(d.ptr))TEMPLATE1;
         d.funcptr = cast(typeof(d.funcptr))TEMPLATE2;
         return d(args);
     }

	// A placeholder to help get the size of functionTemplate
     static void functionTemplateEnd() {asm {naked; nop;} }

	// searches a and replaces matches from and rewrites to to
     static void replaceWord(void[] a, size_t from, size_t to)
     {
         foreach (i; 0..a.length - size_t.sizeof + 1)
         {
             auto p = cast(size_t*)(a.ptr + i);
             if (*p == from)
             {
                 *p = to;
                 return;
             }
         }
         assert(0);
     }


	// Gets the length, in bytes, of the thunk and a slice to it's 
instructions
	auto functionTemplatePtr = cast(size_t*)&functionTemplate;
	auto length = cast(size_t)((cast(size_t*)&functionTemplateEnd - 
functionTemplatePtr));
     auto functionTemplateInstructions = 
functionTemplatePtr[0..length];

     // must allocate type with pointers, otherwise GC won't scan 
it
     auto newFunctionInstructions = new size_t[length + 3 + 10];
	
     // store context in ptr-aligned boundary, so the GC can find 
it. This is just so delegate won't be released.
     newFunctionInstructions[0] = cast(size_t)d.ptr;
     newFunctionInstructions[1] = cast(size_t)d.funcptr;
     newFunctionInstructions = newFunctionInstructions[2..$];

	// Copy old instructions to new instructions
	newFunctionInstructions[0..length] = 
functionTemplateInstructions[0..length];
		
	// Stores this in "thunk data"(local space in function)
     replaceWord(newFunctionInstructions, TEMPLATE1, 
cast(size_t)d.ptr);
     replaceWord(newFunctionInstructions, TEMPLATE2, 
cast(size_t)d.funcptr);

	// Make code executable
     makeExecutable(newFunctionInstructions);

	// return thunk(which wraps original delegate to be called)
     return cast(typeof(return)) newFunctionInstructions.ptr;
}





static struct sExtThread
{

	private __gshared
	{
		bool paused = false;
		bool terminated = false;	
		uint _ID = 0;
		HANDLE _Handle;
	
	
		Duration Call_Delay = dur!("msecs")(100);
		Duration Paused_Wait = dur!("msecs")(1000);
		void function() callback;	
		void delegate() originalCallback;
	}

	
		
	alias callbackType = extern (Windows) uint function(void*);	
	
	public void Create(void delegate() c, bool suspended = false, 
uint stackSize = 16000)
	{	
		originalCallback = c;
		callback = Delegate2Function(c);
				
		auto del = cast(callbackType)Delegate2Function((void*)
		{
		 	import core.thread;
			do
			{
				if (!paused)
					do				
					{
						Thread.sleep(Call_Delay);
						if (!terminated)
							callback();
						else
							paused = true;
					} while(!paused && !terminated);
				else
				{
					Thread.sleep(Paused_Wait);
				}
			} while(!terminated);

			return 0;

		}
		);

		_Handle = CreateThread(cast(SECURITY_ATTRIBUTES*)null, 
stackSize, del, null, (suspended) ? CREATE_SUSPENDED : 0, &_ID);
	}

	public @property HANDLE Handle() { return _Handle; }
	public @property int ID() { return _ID; }

	public void Pause()
	{
		paused = true;		
	}

	public void Resume()
	{
		paused = false;
	}

	// Terminates the thread when it is finished executing at least 
one cycle.
	public void Terminate()
	{
		terminated = true;
	}

	public void Now()
	{
		originalCallback();		
	}

	~this()
	{
		if (!terminated)
			TerminateThread(Handle, 0);
		terminated = true;
		
	}
}


private sExtThread bThread;




static class Data
{
	static __gshared
	{

	}

	static void Init()
	{

		
	}

	static double getCpu()
	{
		return 0;	
	}

	static ulong getMem()
	{
		return 0;	
	}

	static ulong getVMem()
	{
		return 0;	
	}
}

	private void RTStatsCollector()
	{
		Data.Init();
		
		bThread.Create(
		(){
				UpdateStats();
		});
		
    	}




	public static void UpdateStats()	
	{
			
			with(Data)
			{

			}
	}


void main()
{
     RTStatsCollector();
	
	import std.random;

	while(getchar() != EOF)
	{
		auto x = new int[std.random.uniform(1000000, 10000000)];

		writeln("--------");
		bThread.Now();

	}

	getchar();
}



More information about the Digitalmars-d-learn mailing list