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();
}

Reply via email to