in reply to Re^9: threading a perl script
in thread threading a perl script

in threads.xs I see
thread->interp = perl_clone(aTHX, CLONEf_KEEP_PTR_TABLE | CLONEf_C +LONE_HOST);
in win32\perlhost.h(1830)PerlProcFork I see
PerlInterpreter *new_perl = perl_clone_using((PerlInterpreter*)aTH +X, CLONEf_COPY_STACKS, h->m_pHostperlMem, h->m_pHostperlMemShared, h->m_pHostperlMemParse, h->m_pHostperlEnv, h->m_pHostperlStdIO, h->m_pHostperlLIO, h->m_pHostperlDir, h->m_pHostperlSock, h->m_pHostperlProc );
well, instead of perl_clone there is a call to perl_clone_using. and perl_clone calls perl_clone_using.
This does not surprise me - this is what I actually expected to see.

So, I still fail to see why my misunderstanding is manifest.

Replies are listed 'Best First'.
Re^11: threading a perl script
by BrowserUk (Patriarch) on Apr 25, 2011 at 18:59 UTC
    this is what I actually expected to see.

    So till now you hadn't looked. So, you were assuming.

    But, even now you have seen, I think you are still not really seeing or you would not say:

    I still fail to see why my misunderstanding is manifest.

    If you understood what you have now seen. That is, if you were appreciating the implications of the differences between the two pieces of code you've posted.

    Perhaps this will fill in some of the blanks.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      Yes, you're correct -
      I was assuming that 1) threads.xs and 2) fork - they both use same underlying engine - ithreads.
      I even not bothered to look into implementation details, as it was just enough granulation of details for my particular purposes

      Now you're stating that 1) my misunderstanding is manifest and 2) devil in details.

      Now this boils down to one of things:

      • either, when looking into deep into implementation details I will see that 'fork' and 'threads.xs' are really different beasties, due to devils in details
      • or, looking into API that is followed by your link I will eventually understand deep differences between 'threads.xs' and 'fork'
      what should break my wrong assumption?
      I still fail to see a point of my misunderstanding.

      Actually I am inclined to think that my phrases were not clear , they were too vague, due to my English language imperfection, and - so - I do not have deep misunderstanding.

      I.e. I do not know about exact implementation details, but I do know that both are using 'ithreads'.

        Anonymonk pointed out that:

        you're conflating unrelated things, fork is not implemented using threads module

        In reply to a post where you used a bug in Perl's Windows fork emulation as a justifiction for not using threads, nor even building your *nix perl with threading enabled.

        Your misunderstanding is to equate all bugs with the former, as bugs with the latter also. They most frequently are not. Here is a simplified explanation of that.

        Anyone that does not use the fork emulation, either because--like me--they do not see any advantage to it; or because--like you--they use an OS that doesn't need fork to be emulated, will not be affected by bugs in that emulation, even though they might use threads regularly.

        Although both are based around the concept of running a separate interpreter in a new thread--ithreads. They are implemented in quite different ways (with some common code), to achieve quite different things.

        When the code reference passed to thread->create() starts running, it is at the very root of the call-stack in its interpreter. That is, it inherits access to pre-existing code and data, but its call-stack, and all its other stacks, are empty. There are no pending returns to be returned from. No complex of unclosed scopes to be unwound. No half executed if statement that must be conditionally branched.

        Just a coderef that must be executed in the context of some preloaded code and data. Pretty much exactly the same as when main::main is called in a new, single threaded program. That is, all the use statements have been processed, all the BEGIN/CHECK/INIT blocks have been run; some namespaces, coderefs and data have been preloaded, and it is time to run the program.

        The only real differences between the 'new thread' case and the 'new process' case are: a) the entrypoint isn't called main:main; b) the namespaces, coderefs and data didn't need to be loaded from disk, source code parsed and tokenised, opcode trees built etc. A quick block copy and it is ready to go.

        Contrast that with the fork emulation case where the program is already in mid-flow. The program is usually in the middle of a if statement; often embedded within a half executed loop; usually several layers, and potentially dozens of layers of scope down. Potentially in a recursive call chain. Perhaps within a BEGIN or END block. Maybe embedded within several layers of to-be-unwound exception handling. Perhaps with unhandled pending signals, timers or whatever.

        In order for the fork to work, all of this state--half executed opcode stack, code stack, save stack, temp stack, curstack and mark stack--have to be captured and faithfully reproduced, in addition to the preloaded state that a new thread needs. And the scope [sic] for getting that lot wrong is far greater than simply copying the preloaded state required by a new thread.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.