a „oeµã@sjdZddlZddlZddlZddlZddlZddlZddlm Z dZ Gdd„de ƒZ e dkrfe  d¡dS) a–Testing pasing object between multiple COM threads Uses standard COM marshalling to pass objects between threads. Even though Python generally seems to work when you just pass COM objects between threads, it shouldnt. This shows the "correct" way to do it. It shows that although we create new threads to use the Python.Interpreter, COM marshalls back all calls to that object to the main Python thread, which must be running a message loop (as this sample does). When this test is run in "free threaded" mode (at this stage, you must manually mark the COM objects as "ThreadingModel=Free", or run from a service which has marked itself as free-threaded), then no marshalling is done, and the Python.Interpreter object start doing the "expected" thing - ie, it reports being on the same thread as its caller! Python.exe needs a good way to mark itself as FreeThreaded - at the moment this is a pain in the but! éNé)Ú InterpCasec@sFeZdZdd„Zdd„Zdd„Zdd„Zdd d „Zd d „Zdd„Z dS)ÚThreadInterpCasec Cs*z| |¡Wt |¡n t |¡0dS©N)Ú_doTestInThreadÚ win32eventZSetEvent)ÚselfZ stopEventÚinterp©r ú:C:\Program Files\Certbot\pkgs\win32com\test\testMarshal.pyÚ_testInterpInThread&s z$ThreadInterpCase._testInterpInThreadcCsDt ¡t ¡}tr.t |tj¡}tj  |¡}|  d¡t  ¡dS)Nzimport win32api) Ú pythoncomZ CoInitializeÚwin32apiZGetCurrentThreadIdÚ freeThreadedZCoGetInterfaceAndReleaseStreamÚ IID_IDispatchÚwin32comÚclientÚDispatchZExecZCoUninitialize)rr ZmyThreadr r r r,sÿ  z ThreadInterpCase._doTestInThreadc Csˆtj d¡}g}g}t|ƒD]^}t dddd¡}| |¡t tj |j ¡}t j |j ||fd}| d¡| ¡| |¡qd}||fS)zÕCreates multiple threads using simple (but slower) marshalling. Single interpreter object, but a new stream is created per thread. Returns the handles the threads will set when complete. úPython.InterpreterNr©ÚtargetÚargsr)rrrÚrangerÚ CreateEventÚappendr Ú%CoMarshalInterThreadInterfaceInStreamrÚ_oleobj_Ú threadingÚThreadr Ú setDaemonÚstart) rÚ numThreadsr ÚeventsÚthreadsÚiÚhEventZ interpStreamÚtr r r ÚBeginThreadsSimpleMarshal:s"   ÿ ÿ  z*ThreadInterpCase.BeginThreadsSimpleMarshalcCsˆtj d¡}tr t tj|j¡}g}g}t|ƒD]N}t   dddd¡}t j |j ||fd}| d¡| ¡| |¡| |¡q0||fS)zÚCreates multiple threads using fast (but complex) marshalling. The marshal stream is created once, and each thread uses the same stream Returns the handles the threads will set when complete. rNrrr)rrrrr rrrrrrrrr rr r)rr!r r"r#r$r%r&r r r ÚBeginThreadsFastMarshalWs ÿ    z(ThreadInterpCase.BeginThreadsFastMarshalrcCsê|dƒ\}}d}z”|r&t dd|¡}nt |ddtj¡}|tjkrn|tjt|ƒkrn|d}|t|ƒkr¢Wq¾n4|tjt|ƒkrŠt ¡ntdt  ¡t  ¡fƒWqt yºYq¾Yq0q|D]}|  d¡|  | ¡d¡qÂd}dS)NériÐrz:Waiting for thread to stop with interfaces=%d, gateways=%dzthread failed to stop!?)r ZCoWaitForMultipleHandlesrZMsgWaitForMultipleObjectsZ QS_ALLINPUTZ WAIT_OBJECT_0ÚlenZPumpWaitingMessagesÚprintZ_GetInterfaceCountZ_GetGatewayCountÚKeyboardInterruptÚjoinZ assertFalseÚis_alive)rÚfnZbCoWaitr#r"Z numFinishedÚrcr&r r r Ú_DoTestMarshalns8  ÿÿþ  ÿÿ   zThreadInterpCase._DoTestMarshalcCs| |j¡dSr©r1r'©rr r r ÚtestSimpleMarshal•sz"ThreadInterpCase.testSimpleMarshalcCs| |jd¡dS)Nrr2r3r r r ÚtestSimpleMarshalCoWait˜sz(ThreadInterpCase.testSimpleMarshalCoWaitN)r) Ú__name__Ú __module__Ú __qualname__r rr'r(r1r4r5r r r r r%s 'rÚ__main__Z testMarshal)Ú__doc__rZunittestr rZwin32com.clientrrZ testServersrrrr6Úmainr r r r Ús z