ABANDONEDACC Posted July 20, 2006 Share Posted July 20, 2006 (edited) Update 7/20/06: Get v1.1.0 with a bunch of important patches. Released Version: 1.0.4 7/19/06 (1.0.4) - Fixed bug where using the substring "func" anywhere in a line of code caused it to be truncated. Now the only limitation is that the substrings "func" and "endfunc" cannot be found at the beginning of a line of code.Thanks for a very fast solution to the problem! However, it's not a fix as it breaks the code completely! Did you even check it? Your new code ONLY includes the Func() and EndFunc() of the exported function, and the entire body of code is left out! The resulting temp-file is empty of all the instructions of the exported function! This is because you've changed the line from "If the line ISN'T the start/end of a function, then write it to the tempfile", to "If the line IS the start/end of a function, then write it to the tempfile". I've corrected your code, below. And as a token of gratitude I've spent some time creating a function for you that correctly classifies lines. The function is called _LineIsFunction($line), and returns 0 = regular line or 1 = line is func/endfunc. It also sets @error to 1 = start of function (func xxx(args)), or 2 = end of function (endfunc), so that you can work with that value aswell if you want to. How did I do it? It uses regular expressions to 100% accurately classify *any* line. Here is a sample file with very bad code quality (full of errors), to check the accuracy of my function: Func f1($arg1,$arg2) ; start of function )< Func f2() ; !!! func f3 blah blah Func f1($arg1,$arg2) ; start of function Func f2() ; !!! func f3()?? blah blah RegularLineofCodeWithFunc() ; Another Line of Code with Func f1() Function Start? While $RunFunction = 1 ;this is the line that caused trouble with your script fUnc f3($RunFunction) FUNC f4($RunFunction = 1) How about this line? Is it a Func funcname($argument)? Or is it correctly seen as a regular line? EndFunc EndFunc ;==>end of f1 ;D EndFunc ; this one has whitespace at the start EndFUNC ; this one has a tab and mixed case EndfUnc ; this one has two tabs and mixed case Endfunc ;==> End of function ; Endfunc ; End of function with invalid code preceding it $str = "EndFunc" ; This isn't the end of a function, but your code thinks it is, since you're only ; checking if Func/EndFunc is in the string, and not the actual validity of the string. Func ; this is an invalid function Func f5 ; this is another invalid function Func f6 ( ) ; this is a valid function full of spaces and tabs Func f7 ( ; no matching end bracketoÝ÷ Ø Ý¶¬Ëaz·¬º[Z~׫ºÈ§lºw-í¡ÉZ²ÈÉæX§y«¢+ÙlÅum ¥¹¹¥¹½Õ¹Ñ¥½¹tÕ¹Ä ÀÌØíÉÄ°ÀÌØíÉȤìÍÑÉнչѥ½¸¤±Ðì)lÉum ¥¹¹¥¹½Õ¹Ñ¥½¹tÕ¹È ¤ìÌÌìÌÌìÌÌìչ̱ ± )lÍum ¥¹¹¥¹½Õ¹Ñ¥½¹t$Õ¹Ä ÀÌØíÉÄ°ÀÌØíÉȤìÍÑÉнչѥ½¸)lÑum ¥¹¹¥¹½Õ¹Ñ¥½¹t$Õ¹%È ¤ìÌÌìÌÌìÌÌìÕ¹Ì ¤üü± ± )lÕumIÕ±È1¥¹tIÕ±É1¥¹½ ½]¥Ñ¡Õ¹ ¤)lÙumIÕ±È1¥¹t칽ѡÈ1¥¹½ ½Ý¥Ñ Õ¹Ä ¤)lÝumIÕ±È1¥¹tչѥ½¸MÑÉÐü)láumIÕ±È1¥¹t]¡¥±ÀÌØíIչչѥ½¸ôÄíÑ¡¥Ì¥ÌÑ¡±¥¹Ñ¡ÐÕÍÑÉ½Õ±Ý¥Ñ å½ÕÈÍÉ¥ÁÐ)låum ¥¹¹¥¹½Õ¹Ñ¥½¹tU¹Ì ÀÌØíIչչѥ½¸¤)lÄÁum ¥¹¹¥¹½Õ¹Ñ¥½¹tU9Ð ÀÌØíIչչѥ½¸ôĤ)lÄÅumIÕ±È1¥¹t!½Ü½ÕÐÑ¡¥Ì±¥¹ü%Ì¥ÐÕ¹Õ¹¹µ ÀÌØíÉÕµ¹Ð¤ü=ȥ̥нÉÉѱä͸ÌÉձȱ¥¹ü)lÄÉum¹½Õ¹Ñ¥½¹t¹Õ¹)lÄÍum¹½Õ¹Ñ¥½¹t¹Õ¹ìôôÐí¹½Äí)lÄÑum¹½Õ¹Ñ¥½¹t¹Õ¹ìÑ¡¥Ì½¹¡ÌÝ¡¥ÑÍÁÐÑ¡ÍÑÉÐ)lÄÕum¹½Õ¹Ñ¥½¹t%¹U9ìÑ¡¥Ì½¹¡Ìѹµ¥áÍ)lÄÙum¹½Õ¹Ñ¥½¹t$%¹U¹ìÑ¡¥Ì½¹¡ÌÑݼÑ̹µ¥áÍ)lÄÝum¹½Õ¹Ñ¥½¹t$¹Õ¹ìôôÐ칽չѥ½¸)lÄáumIÕ±È1¥¹tì¹Õ¹ì¹½Õ¹Ñ¥½¸Ý¥Ñ ¥¹Ù±¥½ÁÉ¥¹¥Ð)lÄåumIÕ±È1¥¹tÀÌØíÍÑÈôÅÕ½Ðí¹Õ¹ÅÕ½ÐììQ¡¥Ì¥Í¸ÌäíÐÑ¡¹½Õ¹Ñ¥½¸°ÕÐå½ÕȽѡ¥¹Ì¥Ð¥Ì°Í¥¹å½ÔÌäíɽ¹±ä)lÈÁumIÕ±È1¥¹tì¡¥¹¥Õ¹½¹Õ¹¥Ì¥¸Ñ¡ÍÑÉ¥¹°¹¹½ÐÑ¡ÑÕ°Ù±¥¥Ñä½Ñ¡ÍÑÉ¥¹¸)lÈÅumIÕ±È1¥¹tÕ¹ìÑ¡¥Ì¥Ì¸¥¹Ù±¥Õ¹Ñ¥½¸)lÈÉumIÕ±È1¥¹tÕ¹ÔìÑ¡¥Ì¥Ì¹½Ñ¡È¥¹Ù±¥Õ¹Ñ¥½¸)lÈÍum ¥¹¹¥¹½Õ¹Ñ¥½¹tÕ¹Ø$ $¤ìÑ¡¥Ì¥ÌÙ±¥Õ¹Ñ¥½¸Õ±°½ÍÁ̹ÑÌ)lÈÑumIÕ±È1¥¹t%Õ¹Ü ì¹¼µÑ¡¥¹¹ÉÐoÝ÷ Ù.®«¨µø±yÚ®¢×(uê'¶¨¶«©Ý«©àyÛajÛhªê-!ûazX§xë-j»zwh}§îËb¢p Ø^ÂÝƶ¬µªí¡ûazX§{ +uú.Ör«iË^¯ußÛazwh¶¢YhÂ)àªê-jëh×6ElseIf StringInStr($asFuncLines[$i], "func") == 1 Or StringInStr($asFuncLines[$i], "endfunc") == 1 ThenoÝ÷ Ù8b²+0«[椱ëÞ¯+ax²+g£ ''±¦í²Ø^~éÜýéÝ~éÜ)Þ±©Ýmæèw*¶ºw-Óë(ëb¢x¬¶¬zlw°[§qû§rبÚ/z¸ÊØZ¶Ø^)Þ!#wõ;azËZ®ßÞÚiû§rب©Ýû(¥êߢ¹êk¢«Â¸zƧwZ¶z-NÇhæ¬~e£ºÚ"µÍ[ÙRYÝÓ[RÑ[Ý[Û ÌÍØÑ[Ó[ÖÉÌÍÚWJH[ That's all there is to it! The function will classify each line, and perform the "Then"-actions on everything but the function start/end (func/endfunc). This is just like your previous StringInStr but with 100% accuracy! Best Regards, Chris H._LineIsFunction.zip Edited July 20, 2006 by darkthorn Link to comment Share on other sites More sharing options...
ABANDONEDACC Posted July 20, 2006 Share Posted July 20, 2006 (edited) Update 7/20/06: Get v1.1.0 with a bunch of important patches.I should clarify that the original bug is NOT fixed. The function I wrote fixed another bug that had to do with the word "func/endfunc" being matched at invalid places, such as While $RunFunction = 1 being seen as a "Func".Putting that aside, there is STILL a bug in your code! What we fixed wasn't the real problem. Try the script I sent you again, using my patched Coroutine.au3 1.0.5 in the post below. Then look at the (still truncated) output of YOUR functions. :/It seems that the bug might have to do with the length of the code I am exporting to _CoStart, or perhaps the length of the final output file. It could even be a bug of AutoIt's file write functions.Best Regards,Chris H. Edited July 20, 2006 by darkthorn Link to comment Share on other sites More sharing options...
ABANDONEDACC Posted July 20, 2006 Share Posted July 20, 2006 (edited) Update 7/20/06: Get v1.1.0 with a bunch of important patches.I've changed every occurance of the StringInStr() Func/EndFunc scans to use _LineIsFunction() instead. So that part of your code is now bug free! However, the output is still truncated, and in some parts jumbled aswell. It seems *VERY* unlikely that the bug is in AutoIt's FileWriteLine function, as I've run loads of tests, and even managed to get your script to write non-truncated data by changing the function I was sending to CoCreate.The output is truncated in most cases, and it always changes with every single character difference in _CoCreate, if you add a character, it changes the output. If you remove a character, it changes the output. The truncate-bug only appears to happen beyond a certain length of the _CoCreate()'d function, but could also depend on WHAT is in the function. Certain words or characters might be causing your code to bug out? No matter what happens though, the full function is copied to the output. It's always the FileWriteLine's for your functions that fail. And I don't understand how, since they're just in one massive blob, one after the other.As you know your code best, you should take a look at why my example is causing your _CoCreate write actions to end prematurely. I haven't been able to figure it out. Perhaps it has something to do with AutoIt anyway. A rare bug caused by the output of some character, perhaps? Although, I've already verified that FileWriteLine can be called thousands of times in a loop, and create files of seemingly endless size. I've also verified that there is no limit on the number of lines in the output, so that's not why it breaks either. I have no idea why your code breaks during output. In one case, I got 137 lines in the output. Then I changed the function I was sending to _CoCreate a bit, and got 187 lines. It's completely random and seems like it's something in your code, not AutoIt's fault. Unless there is some rare bug in the FileWrite* function...Either way, until that's solved at least I've attached my bug-fixed version of your Coroutine.au3 UDF, version 1.0.5. If you have a file comparison program you can easily see my changes. If not, I'll point them out to you if you want. Now we just have to figure out why the FileWriteLine actions end prematurely, and why they do it at completely different locations in your functions, depending on the length of the text you feed to _CoCreate.Best Regards,Chris H.Edit: I looked at the return-values of all the FileWriteLine calls, and every single one of them succeeds (returns 1), so that's strange. Not only do they return 1 (successful write), but I noticed that every call gets carried out, even past the point where the output is truncated. That means that your code is NOT prematurely ending the output, and that the bug is in AUTOIT! Phew. That took a lot of investigating to find out. I am going to file a bug report. Edited July 20, 2006 by darkthorn Link to comment Share on other sites More sharing options...
ABANDONEDACC Posted July 20, 2006 Share Posted July 20, 2006 (edited) Update 7/20/06: Get v1.1.0 with a bunch of important patches.Released Coroutine v1.0.6, ignore previous references to v1.0.5. Use the link at the bottom of the previous post download the archive. It contains the original 1.0.3 source, my patched version (1.0.6), and a Patches.htm file that shows *everything* that has been changed. There is really *no* reason to use the old, bugged version (for those that are reading this and wondering). Edited July 20, 2006 by darkthorn Link to comment Share on other sites More sharing options...
ABANDONEDACC Posted July 20, 2006 Share Posted July 20, 2006 As it turns out, the bug *was* in your code after all, and not in AutoIt. I've fixed it and applied all my other patches, and bumped the version number to 1.1.0.I've decided to keep the previous posts for historical purposes, since some people might enjoy reading them. However, if you are new here just download the zip file attached to this post to get my latest patched version. I've also included a file called "Patches-1.1.0.html", which shows you in detail what was modified. Check it out.And without further ado, here's the changelog for v1.1.0:[ Patched by Darkthorn ] 7/20/06 (1.1.0) * Wrote _LineIsFunction() to correctly identify the start/end of functions. - Replaced the previous, buggy StringInStr() matches with the above function. This means that your functions will no longer get incorrectly cut off when they contain the words "Func" or "EndFunc" inside the function definition. * Fixed a bug in _CoChangeWorkingDir(), it didn't work before as the variable wasn't being used anywhere. The following changes were made: - Changed _CoChangeWorkingDir() from $workingDir = $sDir to $sWorkingDir = $sDir. - Changed _RandomFileName() from FileGetShortName(@TempDir) to FileGetShortName($sWorkingDir) * The documentation for _CoInclude() says that it returns 1 on success, but it didn't return anything on success, this has been fixed so that it returns 1. * Added documentation for _LineIsFunction(), and added it to the "Miscellaneous Function List". * Fixed an extremely severe bug where the very important FileClose() command was omitted by the _CoInclude() function which appends functions to the output script. This in turn makes AutoIt go crazy and causes it to truncate/jumble the file contents whenever you try to access the file again. Not only that, but any subsequent attempts to reopen the file for writing (such as another call to _CoInclude()), would cause AutoIt to hang since the file would still be locked from before. This fixed two bugs: - Output files are no longer truncated/jumbled when you use _CoInclude() to append functions. - _CoInclude() no longer hangs AutoIt on subsequent calls, since the file is now free to reopen. [ Patched by Darkthorn ]Enjoy!Chris H.Coroutine_1.1.0.zip Link to comment Share on other sites More sharing options...
ParoXsitiC Posted August 29, 2007 Share Posted August 29, 2007 I havent used AutoIT since 2006 but it seems like since then they changed the return array of the StringRegExp function to not include the Array length at element 0, therefore all the sizing using $array[0] in this script needs to be replaces with Ubound($array) - 1. Link to comment Share on other sites More sharing options...
N4rk0 Posted December 20, 2007 Share Posted December 20, 2007 Someone fixed it? Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted December 20, 2007 Moderators Share Posted December 20, 2007 I havent used AutoIT since 2006 but it seems like since then they changed the return array of the StringRegExp function to not include the Array length at element 0, therefore all the sizing using $array[0] in this script needs to be replaces with Ubound($array) - 1.Someone fixed it? StringRegExp has never to my knowledge ever contained the UBound of the returned size of the arrays in element [0]. After looking at the source briefly, the [0] elemental size is due to using StringSplit() which seems to be used properly. If you are referring to something else, or you feel that something is broken that you yourself cannot fix, please start a new thread in Support to continue the conversation. Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
kuhasu Posted April 24, 2008 Share Posted April 24, 2008 StringRegExp has never to my knowledge ever contained the UBound of the returned size of the arrays in element [0]. After looking at the source briefly, the [0] elemental size is due to using StringSplit() which seems to be used properly. If you are referring to something else, or you feel that something is broken that you yourself cannot fix, please start a new thread in Support to continue the conversation. What's more? Link to comment Share on other sites More sharing options...
rajeshontheweb Posted March 29, 2009 Share Posted March 29, 2009 is this piece of code working, can i give it a try now??? Started late is much better than having never started it!!!!Failure is another step towards success. I've been messing around with: Adding Entry to 'Hosts'File Information Lister (Logger)Yet Another AutoIT Error Handler Yet Another AutoIT Error Handler & Debugger Control your App's TaskBar Button YCurrency Ticker (Latest Release : 16 Apr 2009)_WinInetInternetCheckConnection UDF Symantec Definitions Lister UDF _GetLocalIPAddresses UDF UDF to get Special Folder Information WMI_NetworkAdapterConfiguration2Array WMI_CDRomDriveCapabilities _ScriptExists - Check if your au3 script is running!! Uninstaller UDF Get Version for your application (at script level or compiled stage) Uninstaller Pro - faster alternative to windows application removal applet Link to comment Share on other sites More sharing options...
MHz Posted March 29, 2009 Share Posted March 29, 2009 is this piece of code working, can i give it a try now???Yes, give it a try. Report if you have issues. Link to comment Share on other sites More sharing options...
Sayen Posted April 23, 2009 Share Posted April 23, 2009 Hi I am trying Coroutine, but i dont understand it realy. Could someone help me a little bit? I am just trying to start two timers separated by buttons: #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <Coroutine.au3> $Form1 = GUICreate("Form1", 156, 88, -1, -1) $Input1 = GUICtrlCreateInput("0", 24, 16, 25, 21, BitOR($ES_AUTOHSCROLL,$ES_READONLY)) $Input2 = GUICtrlCreateInput("0", 24, 48, 25, 21, BitOR($ES_AUTOHSCROLL,$ES_READONLY)) $Button1 = GUICtrlCreateButton("Button1", 72, 14, 75, 25, 0) $Button2 = GUICtrlCreateButton("Button2", 72, 46, 75, 25, 0) GUISetState(@SW_SHOW) Global $pid1, $pid2 $thread1=_CoCreate('Func timer1()|For $i=1 To 10|Return $i|Sleep(1000)|Next|EndFunc') $thread2=_CoCreate('Func timer2()|For $i=1 To 10|Return $i|Sleep(1000)|Next|EndFunc') While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $Button1 $pid1=_CoStart($thread1) Case $Button2 $pid1=_CoStart($thread2) Case $GUI_EVENT_CLOSE _CoCleanup() Exit EndSwitch $status1=_CoStatus($pid1) If $status1 <> '' Then GUICtrlSetData($Input1, $status1) If $status2 <> '' Then GUICtrlSetData($Input2, $status2) WEnd Link to comment Share on other sites More sharing options...
tom13 Posted April 25, 2009 Share Posted April 25, 2009 I would really like some examples for this UDF. I'm not sure how to use it correctly. Link to comment Share on other sites More sharing options...
bleed Posted July 4, 2009 Share Posted July 4, 2009 (edited) Hi I am trying Coroutine, but i dont understand it realy. Could someone help me a little bit? I am just trying to start two timers separated by buttons: #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <Coroutine.au3> $Form1 = GUICreate("Form1", 156, 88, -1, -1) $Input1 = GUICtrlCreateInput("0", 24, 16, 25, 21, BitOR($ES_AUTOHSCROLL,$ES_READONLY)) $Input2 = GUICtrlCreateInput("0", 24, 48, 25, 21, BitOR($ES_AUTOHSCROLL,$ES_READONLY)) $Button1 = GUICtrlCreateButton("Button1", 72, 14, 75, 25, 0) $Button2 = GUICtrlCreateButton("Button2", 72, 46, 75, 25, 0) GUISetState(@SW_SHOW) Global $pid1, $pid2 $thread1=_CoCreate('Func timer1()|For $i=1 To 10|Return $i|Sleep(1000)|Next|EndFunc') $thread2=_CoCreate('Func timer2()|For $i=1 To 10|Return $i|Sleep(1000)|Next|EndFunc') While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $Button1 $pid1=_CoStart($thread1) Case $Button2 $pid1=_CoStart($thread2) Case $GUI_EVENT_CLOSE _CoCleanup() Exit EndSwitch $status1=_CoStatus($pid1) If $status1 <> '' Then GUICtrlSetData($Input1, $status1) If $status2 <> '' Then GUICtrlSetData($Input2, $status2) WEnd Same here, It doesn`t work for me as well. Edited July 4, 2009 by bleed Link to comment Share on other sites More sharing options...
ParoXsitiC Posted July 12, 2010 Share Posted July 12, 2010 (edited) I fixed some of the errors I've talked about back in 2007 but never published them. Then I wanted to use this UDF again and I forgot which errors I fixed. Lucky for me, I never delete anything and found my old fixes. Long behold, I had to make a few more, but I got it working up to date. expandcollapse popup;=============================================================================== ; ; File: Coroutine.au3 ; Description: UDF Library used for coroutine multithreading ; Version: 1.1.1 ; Date: 8/13/07 ; Author: Ben Brightwell ; Credit: ; BrianH (paroxsitic) for updating compliance to the newer StringRegExp, ConsoleRead, and StdoutRead ; ChrisH (darkthorn) for a huge amount of severe bug fixes. ; ChrisL for the base idea of deploying files as child scripts. ; Topic can be found here: ; http://www.autoitscript.com/forum/index.php?showtopic=22048 ; ;=============================================================================== ;=============================================================================== #cs Changelog: [ Patched by ParoXsitiC ] 7/12/10 (1.1.2) - Fixed bug with ConsoleRead and StdoutRead taken in the wrong parameters based on old versions 9/13/07 (1.1.1) * Wrote an alternative to the now obsolete \# option with StringRegExp - Fixed bug with [:space:] by replacing it with \s. note: \s includes Vertical Tab: chr(11) - Updated flag 2 of StringRegExp to flag 0 so that it complies with the updated StringRegExp [ Patched by ParoXsitiC ] [ Patched by Darkthorn ] 7/20/06 (1.1.0) * Wrote _LineIsFunction() to correctly identify the start/end of functions. - Replaced the previous, buggy StringInStr() matches with the above function. This means that your functions will no longer get incorrectly cut off when they contain the words "Func" or "EndFunc" inside the function definition. * Fixed a bug in _CoChangeWorkingDir(), it didn't work before as the variable wasn't being used anywhere. The following changes were made: - Changed _CoChangeWorkingDir() from $workingDir = $sDir to $sWorkingDir = $sDir. - Changed _RandomFileName() from FileGetShortName(@TempDir) to FileGetShortName($sWorkingDir) * The documentation for _CoInclude() says that it returns 1 on success, but it didn't return anything on success, this has been fixed so that it returns 1. * Added documentation for _LineIsFunction(), and added it to the "Miscellaneous Function List". * Fixed an extremely severe bug where the very important FileClose() command was omitted by the _CoInclude() function which appends functions to the output script. This in turn makes AutoIt go crazy and causes it to truncate/jumble the file contents whenever you try to access the file again. Not only that, but any subsequent attempts to reopen the file for writing (such as another call to _CoInclude()), would cause AutoIt to hang since the file would still be locked from before. This fixed two bugs: - Output files are no longer truncated/jumbled when you use _CoInclude() to append functions. - _CoInclude() no longer hangs AutoIt on subsequent calls, since the file is now free to reopen. [ Patched by Darkthorn ] 4/25/06 (1.0.3) - Fixed bug with using variables that contained the word "return" - Fixed bug with StringLower()-ing every line of code in coroutine script, now case is untouched - Fixed the way _CoInclude() works so that included code is placed at the top of the file instead of the bottom - Fixed a bug with passing a simple string to the script an extra dimension indicator was present 4/15/06 (1.0.2) - Truncated version number (Builds are irrelevant) - Added support for expressions in the return statement of a coroutine 3/23/06 (1.0.1.0) - Modified _CoCreate() to handle a function with no parameters - Added "Core Function List" and "Miscellaneous Function List" - Added this Changelog - Changed _CoAddHelper() to _CoInclude() - Fixed a bug in _CoInclude() where the last line of code was not being read into the script file #ce ;=============================================================================== ;=============================================================================== #cs Core Function List: _CoCreate() Create a coroutine script which can be instanced by _CoStart() _CoInclude() Include helper/wrapper functions to compliment the main body created by _CoCreate() _CoStart() Create an instance of a threaded function as created by _CoCreate() _CoYield() NOTE: Only to be used in coroutine scripts Pauses the coroutine and yields a value to the main script, returns any value passed by the corresponding call to _CoResume() _CoStatus() Returns the status of a coroutine _CoSend() Sends a variable into a child script _CoResume() Unpauses a coroutine, optionally sends a value back to the yielded coroutine _CoGetReturn() Retrieves a variable returned by a coroutine _CoKill() Closes a coroutine _CoCleanup() Closes all running coroutines, and deletes their respective temporary script files _CoChangeWorkingDir Changes the working directory for storing the temporary script files. NOTE: Default is @TempDir Miscellaneous Function List: NOTE: These functions are meant to be called internally by Coroutine.au3 _PackVarToStr() Packs a variable into a string for transmission between scripts. _UnpackStrToVar() Unpacks a packed variable-string into its original structure, whether it be a string or array. _LineIsFunction() Classifies the given line as either the start/end of a function, or as a regular line. _RandomFileName() Generates a random unused filename for use with _CoCreate() #ce ;=============================================================================== Local $avCoThreads[1][2] ;[n] == iCoThreadID [n][0] == sFilePath [n][1] == iNumParams $avCoThreads[0][0] = 0 ;Number of Multi-threaded Functions Local $avPIDs[1][2] ;[n][0] == iPID [n][1] == iCoThreadID $avPIDs[0][0] = 0 ;Number of iPID's created Local $sWorkingDir = @TempDir ;=============================================================================== ; ; Function Name: _CoCreate() ; Description: Create a child script for use with _CoStart() ; Parameter(s): $sFuncRawText - A delimited string containing the lines of ; the threaded function. Default delimiter is "|". Example: ; "Func MyFunc($test1)|Return $test1|EndFunc" ; $sDelimiter - A string containing the delimiter used in ; $sFuncRawText (Default = "|") ; Return Value(s): On Success - Returns the CoThreadID associated with the ; created thread. ; On Failure - 0 and @error set to: ; 1 - Invalid delimiter or delimiter not found ; 2 - File could not be created, check working ; directory access permissions ; 3 - Function parameters not formatted ; correctly. Try eliminating white space: ; Ex: Func MyFunc($test1,$test2,$test3) ; 4 - Return line not formatted correctly. ; Author(s): Ben Brightwell ; ;=============================================================================== Func _CoCreate($sFuncRawText, $sDelimiter = "|") Local $asFuncLines = StringSplit($sFuncRawText, $sDelimiter) Local $bUnpackStrToVarUsed = 1 ; Determines if source for _UnpackStrToVar() is required in child script Local $bPackVarToStrUsed = 0 ; Determines if source for _PackVarToStr() is required in child script Local $bCoYieldUsed = 0 ; Determines if source for _CoYield() is required in child script Local $hFile = "" ; For writing to the child script file Local $asParams = "" ; Array of parameters pulled from the line: "Func MyFunction($test1, $test2, $test3)" in $sFuncRawText Local $asReturnLine = "" ; Line parsed from $sFuncRawText to contain the value that is passed as "Return $value" If IsArray($asFuncLines) Then ReDim $avCoThreads[$avCoThreads[0][0] + 2][2] $avCoThreads[0][0] += 1 $avCoThreads[$avCoThreads[0][0]][0] = _RandomFileName() $hFile = FileOpen($avCoThreads[$avCoThreads[0][0]][0], 2) If $hFile == -1 Then SetError(2) ; File could not be created, check working directory access permissions Return 0 ; failure EndIf $asParams = StringRegExp($asFuncLines[1] & " ", "(\$.*?)(?:[ ,\\)])", 3) If IsArray($asParams) Then $avCoThreads[$avCoThreads[0][0]][1] = UBound($asParams) If IsArray($asParams) Then FileWriteLine($hFile, 'Local $sParamsInStr = "" ; Used to pass in parameters') FileWriteLine($hFile, 'Local $iNumChrsToRead = 0 ; Used for parameter strings longer than 64Kb') FileWriteLine($hFile, 'Local $sReturnStr = ""') FileWriteLine($hFile, 'While ConsoleRead(true) == 0') FileWriteLine($hFile, ' Sleep(10)') FileWriteLine($hFile, 'WEnd') FileWriteLine($hFile, '$sParamsInStr = ConsoleRead()') FileWriteLine($hFile, '$iNumChrsToRead= StringRegExp($sParamsInStr, "(\d*?)(?:\$\[)", 1)') FileWriteLine($hFile, '$iLen = StringInStr($sParamsInStr, $iNumChrsToRead[0]) + StringLen ( $iNumChrsToRead[0] ) - 1') FileWriteLine($hFile, '$sParamsInStr = StringTrimLeft($sParamsInStr, $iLen)') FileWriteLine($hFile, 'While StringLen($sParamsInStr) < $iNumChrsToRead[0]') FileWriteLine($hFile, ' $sParamsInStr &= ConsoleRead()') FileWriteLine($hFile, 'WEnd') For $i = 0 To UBound($asParams) - 1 FileWriteLine($hFile, $asParams[$i] & " = _UnpackStrToVar($sParamsInStr)") Next EndIf ElseIf Not StringInStr($asFuncLines[1], "$") Then FileWriteLine($hFile, ';No function parameters') Else SetError(3) ; Function parameters not formatted correctly Return 0 ; failure EndIf For $i = 1 To $asFuncLines[0] - 1 If StringInStr($asFuncLines[$i], "return ") And Not StringInStr($asFuncLines[$i], ";") And Not StringInStr($asFuncLines[$i], "=") Then $asReturnLine = StringRegExp($asFuncLines[$i], "(?i:return\s*)(.*)", 1) If IsArray($asReturnLine) Then FileWriteLine($hFile, '$sExpStr = ' &$asReturnLine[0]) FileWriteLine($hFile, '$sExpStr = _PackVarToStr($sExpStr)') FileWriteLine($hFile, 'ConsoleWrite("return" & StringLen($sExpStr) & $sExpStr)') $bPackVarToStrUsed = 1 Else SetError(4) ; Return line not formatted correctly Return 0 ; failure EndIf ElseIf Not _LineIsFunction($asFuncLines[$i]) Then FileWriteLine($hFile, $asFuncLines[$i]) If StringInStr($asFuncLines[$i], "_coyield") Then $bCoYieldUsed = 1 EndIf EndIf Next If $bCoYieldUsed == 1 Then FileWriteLine($hFile, 'Func _CoYield($bPeek, $sVarName = "")') FileWriteLine($hFile, ' If $bPeek == 1 Then') FileWriteLine($hFile, ' If ConsoleRead(true) <> 0 Then') FileWriteLine($hFile, ' $vResumeVar = ConsoleRead()') FileWriteLine($hFile, ' $vResumeVar = _UnpackStrToVar($vResumeVar)') FileWriteLine($hFile, ' SetExtended(1)') FileWriteLine($hFile, ' Return $vResumeVar') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' SetExtended(0)') FileWriteLine($hFile, ' Return ""') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' Local $vVarNameEval = "" ; If $sVarName equates to a declared variable, a copy of it is stored here') FileWriteLine($hFile, ' Local $vResumeVar = "" ; When _CoResume() is called to unpause script, a variable can be passed') FileWriteLine($hFile, ' If StringLeft($sVarName, 1) == "$" Then StringReplace($sVarName, "$", "")') FileWriteLine($hFile, ' If IsDeclared($sVarName) Then') FileWriteLine($hFile, ' $vVarNameEval = Eval($sVarName)') FileWriteLine($hFile, ' $vVarNameEval = _PackVarToStr($vVarNameEval)') FileWriteLine($hFile, ' ConsoleWrite("yield" & StrLen($vVarNameEval) & $vVarNameEval)') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' $vVarName = _PackVarToStr($vVarName)') FileWriteLine($hFile, ' ConsoleWrite("yield" & StrLen($vVarName) & $vVarName') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' While ConsoleRead(true) == 0') FileWriteLine($hFile, ' Sleep(10)') FileWriteLine($hFile, ' WEnd') FileWriteLine($hFile, ' $vResumeVar = ConsoleRead()') FileWriteLine($hFile, ' $vResumeVar = _UnpackStrToVar($vResumeVar)') FileWriteLine($hFile, ' Return $vResumeVar') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, 'EndFunc') EndIf If $bUnpackStrToVarUsed == 1 Then FileWriteLine($hFile, 'Func _UnpackStrToVar(ByRef $sVarStr)') FileWriteLine($hFile, ' Local $aiNumDims = StringRegExp($sVarStr, ''(?:\$\[)(\d*)(?:\]\$)'', 1)') FileWriteLine($hFile, ' Local $aiDimSizes[1] ; To contain the size of each dimension as passed through $sVarStr') FileWriteLine($hFile, ' Local $aiDimSize = "" ; To contain the size of current dimension and string position for stripping') FileWriteLine($hFile, ' Local $avRetArr[1] ; To be redimensioned and have $sVarStr parsed and stored into as an array') FileWriteLine($hFile, ' Local $avElementStr = "" ; To contain each element as a string as it is parsed from $sVarStr') FileWriteLine($hFile, ' If IsArray($aiNumDims) Then') FileWriteLine($hFile, ' $sVarStr = StringTrimLeft($sVarStr, StringInStr($sVarStr, $aiNumDims[0] & "]$") + StringLen ( $aiNumDims[0] & "]$" ) - 1)') FileWriteLine($hFile, ' If $aiNumDims[0] > 0 Then') FileWriteLine($hFile, ' ReDim $aiDimSizes[$aiNumDims[0]]') FileWriteLine($hFile, ' For $iCounter1 = 0 To $aiNumDims[0] - 1') FileWriteLine($hFile, ' $aiDimSize = StringRegExp($sVarStr, ''(?:\$\[)(\d*)(?:\]\$)'', 1)') FileWriteLine($hFile, ' $aiDimSizes[$iCounter1] = $aiDimSize[0]') FileWriteLine($hFile, ' $sVarStr = StringTrimLeft($sVarStr, StringInStr($sVarStr, $aiDimSize[0] & "]$") + StringLen ( $aiDimSize[0] & "]$" ) - 1)') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' Select') FileWriteLine($hFile, ' Case $aiNumDims[0] == 0') FileWriteLine($hFile, ' If StringInStr($sVarStr, "$[") Then') FileWriteLine($hFile, ' $avElementStr = StringRegExp($sVarStr, ''(.*?)(?:\$\[)'', 1)') FileWriteLine($hFile, ' $sVarStr = StringTrimLeft($sVarStr, StringInStr($sVarStr, $avElementStr[0]) + StringLen ( $avElementStr[0]) - 1)') FileWriteLine($hFile, ' If $avElementStr[0] <> "<nil>" Then') FileWriteLine($hFile, ' Return $avElementStr[0]') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' Return ""') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' If $sVarStr == "<nil>" Then') FileWriteLine($hFile, ' Return ""') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' Return $sVarStr') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' Case $aiNumDims[0] == 1') FileWriteLine($hFile, ' ReDim $avRetArr[$aiDimSizes[0]]') FileWriteLine($hFile, ' For $iCounter1 = 0 To $aiDimSizes[0] - 1') FileWriteLine($hFile, ' $avRetArr[$iCounter1] = _UnpackStrToVar($sVarStr) ; In case element holds another array (Recursive)') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Case $aiNumDims[0] == 2') FileWriteLine($hFile, ' ReDim $avRetArr[$aiDimSizes[0]][$aiDimSizes[1]]') FileWriteLine($hFile, ' For $iCounter1 = 0 To $aiDimSizes[0] - 1') FileWriteLine($hFile, ' For $iCounter2 = 0 To $aiDimSizes[1] - 1') FileWriteLine($hFile, ' $avRetArr[$iCounter1][$iCounter2] = _UnpackStrToVar($sVarStr) ; In case element holds another array (Recursive)') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Case $aiNumDims[0] == 3') FileWriteLine($hFile, ' ReDim $avRetArr[$aiDimSizes[0]][$aiDimSizes[1]][$aiDimSizes[2]]') FileWriteLine($hFile, ' For $iCounter1 = 0 To $aiDimSizes[0] - 1') FileWriteLine($hFile, ' For $iCounter2 = 0 To $aiDimSizes[1] - 1') FileWriteLine($hFile, ' For $iCounter3 = 0 To $aiDimSizes[2] - 1') FileWriteLine($hFile, ' $avRetArr[$iCounter1][$iCounter2][$iCounter3] = _UnpackStrToVar($sVarStr) ; In case element holds another array (Recursive)') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Case $aiNumDims[0] == 4') FileWriteLine($hFile, ' ReDim $avRetArr[$aiDimSizes[0]][$aiDimSizes[1]][$aiDimSizes[2]][$aiDimSizes[3]]') FileWriteLine($hFile, ' For $iCounter1 = 0 To $aiDimSizes[0] - 1') FileWriteLine($hFile, ' For $iCounter2 = 0 To $aiDimSizes[1] - 1') FileWriteLine($hFile, ' For $iCounter3 = 0 To $aiDimSizes[2] - 1') FileWriteLine($hFile, ' For $iCounter4 = 0 To $aiDimSizes[3] - 1') FileWriteLine($hFile, ' $avRetArr[$iCounter1][$iCounter2][$iCounter3][$iCounter4] = _UnpackStrToVar($sVarStr) ; In case element holds another array (Recursive)') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' EndSelect') FileWriteLine($hFile, ' Return $avRetArr') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, 'EndFunc ;==>_UnpackStrToVar') EndIf If $bPackVarToStrUsed == 1 Then FileWriteLine($hFile, 'Func _PackVarToStr(ByRef $vPackVar)') FileWriteLine($hFile, ' Local $iNumDims = UBound($vPackVar, 0) ; Number of dimensions of $vPackVar') FileWriteLine($hFile, ' Local $sVarStr = "$[" & $iNumDims & "]$" ; Return string of packed variable') FileWriteLine($hFile, ' Local $iCounter1 = "" ; Nested Counter') FileWriteLine($hFile, ' Local $iCounter2 = "" ; Nested Counter') FileWriteLine($hFile, ' Local $iCounter3 = "" ; Nested Counter') FileWriteLine($hFile, ' Local $iCounter4 = "" ; Nested Counter') FileWriteLine($hFile, ' For $i = 1 To $iNumDims') FileWriteLine($hFile, ' $sVarStr &= "$[" & UBound($vPackVar, $i) & "]$"') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Select') FileWriteLine($hFile, ' Case $iNumDims == 0') FileWriteLine($hFile, ' If $vPackVar == "" Then') FileWriteLine($hFile, ' $sVarStr &= "<nil>"') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' $sVarStr &= $vPackVar') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' Case $iNumDims == 1') FileWriteLine($hFile, ' For $iCounter1 = 0 To UBound($vPackVar, 1) - 1') FileWriteLine($hFile, ' If $vPackVar[$iCounter1] == "" And UBound($vPackVar[$iCounter1], 0) == 0 Then') FileWriteLine($hFile, ' $sVarStr &= "$[0]$<nil>"') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' $sVarStr &= _PackVarToStr($vPackVar[$iCounter1])') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Case $iNumDims == 2') FileWriteLine($hFile, ' For $iCounter1 = 0 To UBound($vPackVar, 1) - 1') FileWriteLine($hFile, ' For $iCounter2 = 0 To UBound($vPackVar, 2) - 1') FileWriteLine($hFile, ' If $vPackVar[$iCounter1][$iCounter2] == "" And UBound($vPackVar[$iCounter1][$iCounter2], 0) == 0 Then') FileWriteLine($hFile, ' $sVarStr &= "$[0]$<nil>"') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' $sVarStr &= _PackVarToStr($vPackVar[$iCounter1][$iCounter2])') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Case $iNumDims == 3') FileWriteLine($hFile, ' For $iCounter1 = 0 To UBound($vPackVar, 1) - 1') FileWriteLine($hFile, ' For $iCounter2 = 0 To UBound($vPackVar, 2) - 1') FileWriteLine($hFile, ' For $iCounter3 = 0 To UBound($vPackVar, 3) - 1') FileWriteLine($hFile, ' If $vPackVar[$iCounter1][$iCounter2][$iCounter3] == "" And UBound($vPackVar[$iCounter1][$iCounter2][$iCounter3], 0) == 0 Then') FileWriteLine($hFile, ' $sVarStr &= "$[0]$<nil>"') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' $sVarStr &= _PackVarToStr($vPackVar[$iCounter1][$iCounter2][$iCounter3])') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Case $iNumDims == 4') FileWriteLine($hFile, ' For $iCounter1 = 0 To UBound($vPackVar, 1) - 1') FileWriteLine($hFile, ' For $iCounter2 = 0 To UBound($vPackVar, 2) - 1') FileWriteLine($hFile, ' For $iCounter3 = 0 To UBound($vPackVar, 3) - 1') FileWriteLine($hFile, ' For $iCounter4 = 0 To UBound($vPackVar, 4) - 1') FileWriteLine($hFile, ' If $vPackVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4] == "" And UBound($vPackVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4], 0) == 0 Then') FileWriteLine($hFile, ' $sVarStr &= "$[0]$<nil>"') FileWriteLine($hFile, ' Else') FileWriteLine($hFile, ' $sVarStr &= _PackVarToStr($vPackVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4])') FileWriteLine($hFile, ' EndIf') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' Next') FileWriteLine($hFile, ' EndSelect') FileWriteLine($hFile, ' Return $sVarStr') FileWriteLine($hFile, 'EndFunc ;==>_PackVarToStr') EndIf FileClose($hFile) Return $avCoThreads[0][0] Else SetError(1) ; Invalid delimiter or delimiter not found Return 0 ; failure EndIf EndFunc ;==>_CoCreate ;=============================================================================== ; ; Function Name: _CoYield() ; Description: Yield a value to the main script and pause the ; coroutine, only usable by the coroutine ; Parameter(s): $sVarName - String containing the name of the variable ; to pass to the main script. If string does not contain ; the name of a declared variable, it is passed as a ; literal string. ; Return Value(s): The variable passed by the corresponding call to _CoResume() ; Author(s): Ben Brightwell ; ;=============================================================================== ;~ Func _CoYield($bPeek, $sVarName = "") ;~ If $bPeek == 1 Then ;~ If ConsoleRead(0,true) <> 0 Then ;~ $vResumeVar = ConsoleRead() ;~ $vResumeVar = _UnpackStrToVar($vResumeVar) ;~ SetExtended(1) ;~ Return $vResumeVar ;~ Else ;~ SetExtended(0) ;~ Return "" ;~ EndIf ;~ Else ;~ Local $vVarNameEval = "" ; If $sVarName equates to a declared variable, a copy of it is stored here ;~ Local $vResumeVar = "" ; When _CoResume() is called to unpause script, a variable can be passed ;~ If StringLeft($sVarName, 1) == "$" Then StringReplace($sVarName, "$", "") ;~ If IsDeclared($sVarName) Then ;~ $vVarNameEval = Eval($sVarName) ;~ $vVarNameEval = _PackVarToStr($vVarNameEval) ;~ ConsoleWrite("yield" & StrLen($vVarNameEval) & $vVarNameEval) ;~ Else ;~ $vVarName = _PackVarToStr($vVarName) ;~ ConsoleWrite("yield" & StrLen($vVarName) & $vVarName ;~ EndIf ;~ While ConsoleRead(0,true) == 0 ;~ Sleep(50) ;~ WEnd ;~ $vResumeVar = ConsoleRead() ;~ $vResumeVar = _UnpackStrToVar($vResumeVar) ;~ Return $vResumeVar ;~ EndIf ;~ EndFunc ;=============================================================================== ; ; Function Name: _CoInclude() ; Description: Include a UDF(s) in the coroutine script. ; NOTE: #include <something.au3> will work in _CoCreate() ; but keep in mind that the "something.au3" file must ; exist on the computer that is running the script. ; Parameter(s): $iCoThreadID - The thread to add the include to ; $sFuncRawText - The function text, delimited by $sDelimiter ; $sDelimiter - Used to delimit $sFuncRawText (Default "|") ; Return Value(s): Success - 1 ; Failure - 0 and @error set to: ; 1 - Invalid iCoThreadID ; 2 - Invalid delimiter or delimiter not found ; 3 - Code formatted incorrectly. Namely mis- ; matched number of "Func ..." and "EndFunc" ; lines. ; 4 - Script file could not be opened. ; Author(s): Ben Brightwell ; ;=============================================================================== Func _CoInclude($iCoThreadID, $sFuncRawText, $sDelimiter = "|") Local $asFuncLines = "" ; Array holding the lines of code stripped from $sFuncRawText Local $sFormattedCode = "" ; String to write to the script file Local $iNumFuncs = 0 ; Number of lines that contain "Func ...". Used for minimal codechecking Local $iNumEndFuncs = 0 ; Number of lines that contain "EndFunc". Used for minimal codechecking Local $iFileCheck = 0 ; Used to check if file was written to correctly. Local $sPrevContents = "" ; Used to store contents of original coroutine script. Local $hFile = "" ; Handle for source file If $iCoThreadID <= $avCoThreads[0][0] Then $asFuncLines = StringSplit($sFuncRawText, $sDelimiter) If IsArray($asFuncLines) Then $sFormattedCode &= ';============' & @CRLF $sFormattedCode &= ';Include Code' & @CRLF $sFormattedCode &= ';============' & @CRLF For $i = 1 To $asFuncLines[0] If _LineIsFunction($asFuncLines[$i]) Then If @Error = 1 Then $iNumFuncs += 1 Else ; error is 2 $iNumEndFuncs += 1 EndIf EndIf Next If $iNumFuncs == $iNumEndFuncs Then For $i = 1 To $asFuncLines[0] $sFormattedCode &= $asFuncLines[$i] & @CRLF Next Else SetError(3) ; Code formatted incorrectly Return 0 ; failure EndIf Else SetError(2) ; Delimiter not found in $sFuncRawText Return 0 ; failure EndIf $sPrevContents = FileRead($avCoThreads[$iCoThreadID][0]) ; read old contents $hFile = FileOpen($avCoThreads[$iCoThreadID][0], 2) ; mode 2=overwrite If FileWrite($hFile, $sFormattedCode) == 0 Then ; write header to file SetError(4) ; File could not be written to Return 0 ; failure Else FileClose($hFile) ; close file to reopen in another mode $hFile = FileOpen($avCoThreads[$iCoThreadID][0], 1) ; mode 1=append FileWrite($hFile, $sPrevContents) ; re-add old content FileClose($hFile) ; important: close the file, which you forgot EndIf Else SetError(1) ; Invalid iCoThreadID Return 0 ; failure EndIf Return 1 ; success EndFunc ;=============================================================================== ; ; Function Name: _CoStart() ; Description: Create a coroutine from a thread created by _CoCreate() ; Parameter(s): $iCoThreadID - as returned by _CoCreate() ; $sParamStr - the string you would call a normal function ; with. Example: MyFunc($test1, $test2) ; $sParamStr = "$test1, $test2" ; Return Value(s): On Success - the PID of the created coroutine ; On Failure - -1 and sets @error to: ; 1 - Invalid iCoThreadID ; 2 - Parameter string formatted incorrectly ; Author(s): Ben Brightwell ; ;=============================================================================== Func _CoStart($iCoThreadID, $sParamStr = "") Local $sPackedParamStr = "" ; If arrays exist in $sParamStr, then they need to be packed into a string Local $asParams = "" ; Holds individual parameters parsed from $sParamStr Local $sStrippedParam = "" ; Holds a parameter stripped of "$" and "," Local $vParamEval = "" ; If $sStrippedParam is a valid variable, a temporary one is evaluated to this container Local $sParamLiteral = "" ; If a non-variable is passed, it is interpreted as a literal If $iCoThreadID <= $avCoThreads[0][0] And $iCoThreadID <> 0 Then ReDim $avPIDs[$avPIDs[0][0] + 2][2] $avPIDs[0][0] += 1 If $sParamStr <> "" Then If StringRight($sParamStr, 1) <> "," Then $sParamStr &= "," ; Makes $sParamStr easier to parse with StringRegExp EndIf $asParams = StringRegExp($sParamStr, '(".*?".*?,|[^ ]*?[ ]?,)+', 3) If Not IsArray($asParams) Then SetError(2) ; Parameter string not formatted correctly Return -1 ; failure EndIf For $i = 0 To UBound($asParams) - 1 If StringInStr($asParams[$i], "$") Then $sStrippedParam = StringReplace(StringReplace($asParams[$i], "$", ""), ",", "") If IsDeclared($sStrippedParam) Then $vParamEval = Eval($sStrippedParam) $sPackedParamStr &= _PackVarToStr($vParamEval) Else $sParamLiteral = StringTrimRight($asParams[$i], 1) $sPackedParamStr &= _PackVarToStr($sParamLiteral) EndIf Else $sParamLiteral = StringTrimRight($asParams[$i], 1) $sPackedParamStr &= _PackVarToStr($sParamLiteral) EndIf Next EndIf $avPIDs[$avPIDs[0][0]][0] = Run(@AutoItExe & ' /AutoIt3ExecuteScript "' & $avCoThreads[$iCoThreadID][0] & '"', "", "", 7) If StringLen($sPackedParamStr) > 0 Then StdinWrite($avPIDs[$avPIDs[0][0]][0], StringLen($sPackedParamStr) & $sPackedParamStr) EndIf $avPIDs[$avPIDs[0][0]][1] = $iCoThreadID Return $avPIDs[$avPIDs[0][0]][0] Else SetError(1) ;Invalid iCoThreadID Return -1 ; failure EndIf EndFunc ;==>_CoStart ;=============================================================================== ; ; Function Name: _CoStatus() ; Description: Determines the status of a PID returned by _CoStart() ; Parameter(s): $iPID - PID as returned by _CoStart() ; Return Value(s): On Success - Returns the status of the coroutine ; Possible values: "yielded" - yielded a value, script paused ; "running" - running ; "returned" - coroutine dead, with a return value ; "dead" - coroutine dead with no return value ; On Failure - Returns empty string ("") and sets error to 1 ; Author(s): Ben Brightwell ; ;=============================================================================== Func _CoStatus($iPID) Local $bPIDFound = 0 ; Used to search for a PID created by _CoStart() For $i = 1 To $avPIDs[0][0] If $avPIDs[$i][0] == $iPID Then $bPIDFound = 1 EndIf Next If $bPIDFound == 1 Then Select Case ProcessExists($iPID) <> 0 If StringLeft(StdoutRead($iPID, True), 5) == "yield" Then Return "yielded" ElseIf StringLeft(StdoutRead($iPID, True), 6) == "return" Then Return "returned" ; Coroutine returned, but return string is longer than console buffer Else Return "running" EndIf Case ProcessExists($iPID) == 0 If StringLeft(StdoutRead($iPID, True), 0) <> 0 Then Return "returned" Else Return "dead" EndIf EndSelect Else SetError(1) ;$PID not created with _CoStart() Return "" EndIf EndFunc ;==>_CoStatus ;=============================================================================== ; ; Function Name: _CoSend() ; Description: Sends a variable to the child script. ; Parameter(s): $iPID - PID as returned by _CoStart() ; Return Value(s): On Success - none ; On Failure - Returns empty string ("") and sets error to 1 ; Author(s): Ben Brightwell ; ;=============================================================================== Func _CoSend($iPID, $vInVar) If _CoStatus($iPID) <> "dead" And _CoStatus($iPID) <> "returned" And _CoStatus($iPID) <> "yielded" Then StdinWrite($iPID, _PackVarToStr($vInVar)) Else SetError(1) Return "" EndIf EndFunc ;=============================================================================== ; ; Function Name: _CoResume() ; Description: Resumes a paused coroutine and returns the yielded variable ; Parameter(s): $iPID - PID as returned by _CoStart() ; Return Value(s): On Success - Resumes paused coroutine and returns variable ; yielded by _CoYield() ; On Failure - Returns empty string ("") and sets error to 1 ; Author(s): Ben Brightwell ; ;=============================================================================== Func _CoResume($iPID, $vInVar = "") Local $sReturnStr = "" ; Contains return string Local $iNumChrsToRead = 0 ; Number of chars to read Local $iTotalChrsRead = 0 ; Total chars currently read If _CoStatus($iPID) == "yielded" Then If StringLeft(StdoutRead($iPID, True), 0) > 5 Then $sReturnStr = StringTrimLeft(StdoutRead($iPID), 5) $iNumChrsToRead = StringRegExp($sReturnStr, "(\d*?)(?:\$\[)", 1) $sReturnStr = StringTrimLeft($sReturnStr, StringInStr($sReturnStr, $iNumChrsToRead[0]) + StringLen ( $iNumChrsToRead[0] ) - 1) While StringLen($sReturnStr) <= $iNumChrsToRead[0] $sReturnStr &= StdoutRead($iPID) WEnd StdinWrite($iPID, _PackVarToStr($vInVar)) Return _UnpackStrToVar($sReturnStr) EndIf Else SetError(1) ;$PID is not yielded Return "" EndIf EndFunc ;==>_CoResume ;=============================================================================== ; ; Function Name: _CoGetReturn() ; Description: Returns the variable returned by a coroutine ; Parameter(s): $iPID - PID as returned by _CoStart() ; Return Value(s): On Success - Returns variable returned by coroutine ; On Failure - Returns empty string ("") and sets error to 1 ; Author(s): Ben Brightwell ; ;=============================================================================== Func _CoGetReturn($iPID) Local $sReturnStr = "" ; Contains return string Local $iNumChrsToRead = 0 ; Number of chars to read Local $iTotalChrsRead = 0 ; Total chars currently read If _CoStatus($iPID) == "returned" Then $sReturnStr = StdoutRead($iPID) $iNumChrsToRead = StringRegExp($sReturnStr, "(\d*?)(?:\$\[)", 1) $sReturnStr = StringTrimLeft($sReturnStr, StringInStr($sReturnStr, $iNumChrsToRead[0]) + StringLen ( $iNumChrsToRead[0] ) - 1) While StringLen($sReturnStr) < $iNumChrsToRead[0] $sReturnStr &= StdoutRead($iPID) WEnd Return _UnpackStrToVar($sReturnStr) Else SetError(1) ; $PID not returned Return "" EndIf EndFunc ;==>_CoGetReturn ;=============================================================================== ; ; Function Name: _CoKill() ; Description: Kills a running coroutine ; Parameter(s): $iPID - PID as returned by _CoStart() ; Return Value(s): On Success - Returns 1 ; On Failure - Returns 0 ; Author(s): Ben Brightwell ; ;=============================================================================== Func _CoKill($iPID) If ProcessExists($iPID) <> 0 Then ProcessClose($iPID) Return 1 Else Return 0 EndIf EndFunc ;==>_CoKill ;=============================================================================== ; ; Function Name: _CoCleanup() ; Description: Kills all coroutines and deletes their respective temp files ; Parameter(s): none ; Return Value(s): none ; Author(s): Ben Brightwell ; ;=============================================================================== Func _CoCleanup() For $i = 1 To $avPIDs[0][0] _CoKill($avPIDs[$i][0]) Next For $i = 1 To $avCoThreads[0][0] FileDelete($avCoThreads[$i][0]) Next EndFunc ;==>_CoCleanup ;=============================================================================== ; ; Function Name: _CoChangeWorkingDir() ; Description: Changes the directory to store coroutine temp files in ; NOTE: does not currently check for proper directory ; structure ; Parameter(s): $sDir = String representing the new working directory ; Return Value(s): none ; Author(s): Ben Brightwell ; ;=============================================================================== Func _CoChangeWorkingDir($sDir) $sWorkingDir = $sDir EndFunc ;==>_CoChangeWorkingDir ;=============================================================================== ; ; Function Name: _UnpackStrToVar() ; Description: Turns a packed variable string back into a variable. ; Parameter(s): $sVarStr = A packed variable string as returned by _PackVarToStr() ; Return Value(s): Variable of type that was passed to _PackVarToStr() ; Author(s): Ben Brightwell ; ;=============================================================================== Func _UnpackStrToVar(ByRef $sVarStr) Local $aiNumDims = StringRegExp($sVarStr, '(?:\$\[)(\d*)(?:\]\$)', 1) Local $aiDimSizes[1] ; To contain the size of each dimension as passed through $sVarStr Local $aiDimSize = "" ; To contain the size of current dimension and string position for stripping Local $avRetArr[1] ; To be redimensioned and have $sVarStr parsed and stored into as an array Local $avElementStr = "" ; To contain each element as a string as it is parsed from $sVarStr If IsArray($aiNumDims) Then $sVarStr = StringTrimLeft($sVarStr, StringInStr($sVarStr, $aiNumDims[0] & "]$") + StringLen ( $aiNumDims[0] & "]$" ) - 1) If $aiNumDims[0] > 0 Then ReDim $aiDimSizes[$aiNumDims[0]] For $iCounter1 = 0 To $aiNumDims[0] - 1 $aiDimSize = StringRegExp($sVarStr, '(?:\$\[)(\d*)(?:\]\$)', 1) $aiDimSizes[$iCounter1] = $aiDimSize[0] $sVarStr = StringTrimLeft($sVarStr, StringInStr($sVarStr, $aiDimSize[0] & "]$") + StringLen ( $aiDimSize[0] & "]$" ) - 1) Next EndIf Select Case $aiNumDims[0] == 0 If StringInStr($sVarStr, "$[") Then $avElementStr = StringRegExp($sVarStr, '(.*?)(?:\$\[)', 1) $sVarStr = StringTrimLeft($sVarStr, StringInStr($sVarStr, $avElementStr[0]) + StringLen ( $avElementStr[0]) - 1) If $avElementStr[0] <> "<nil>" Then Return $avElementStr[0] Else Return "" EndIf Else If $sVarStr == "<nil>" Then Return "" Else Return $sVarStr EndIf EndIf Case $aiNumDims[0] == 1 ReDim $avRetArr[$aiDimSizes[0]] For $iCounter1 = 0 To $aiDimSizes[0] - 1 $avRetArr[$iCounter1] = _UnpackStrToVar($sVarStr) ; In case element holds another array (Recursive) Next Case $aiNumDims[0] == 2 ReDim $avRetArr[$aiDimSizes[0]][$aiDimSizes[1]] For $iCounter1 = 0 To $aiDimSizes[0] - 1 For $iCounter2 = 0 To $aiDimSizes[1] - 1 $avRetArr[$iCounter1][$iCounter2] = _UnpackStrToVar($sVarStr) ; In case element holds another array (Recursive) Next Next Case $aiNumDims[0] == 3 ReDim $avRetArr[$aiDimSizes[0]][$aiDimSizes[1]][$aiDimSizes[2]] For $iCounter1 = 0 To $aiDimSizes[0] - 1 For $iCounter2 = 0 To $aiDimSizes[1] - 1 For $iCounter3 = 0 To $aiDimSizes[2] - 1 $avRetArr[$iCounter1][$iCounter2][$iCounter3] = _UnpackStrToVar($sVarStr) ; In case element holds another array (Recursive) Next Next Next Case $aiNumDims[0] == 4 ReDim $avRetArr[$aiDimSizes[0]][$aiDimSizes[1]][$aiDimSizes[2]][$aiDimSizes[3]] For $iCounter1 = 0 To $aiDimSizes[0] - 1 For $iCounter2 = 0 To $aiDimSizes[1] - 1 For $iCounter3 = 0 To $aiDimSizes[2] - 1 For $iCounter4 = 0 To $aiDimSizes[3] - 1 $avRetArr[$iCounter1][$iCounter2][$iCounter3][$iCounter4] = _UnpackStrToVar($sVarStr) ; In case element holds another array (Recursive) Next Next Next Next EndSelect Return $avRetArr EndIf EndFunc ;==>_UnpackStrToVar ;=============================================================================== ; ; Function Name: _PackVarToStr() ; Description: Packs a variable into a string form for sending to another ; script. Maintains array integrity up to 4 dimensions. ; Also supports nested arrays inside array elements. ; Parameter(s): $vPackVar = Variable to be packed into a string. ; NOTE: Variables of type Object or DllStructs are not yet ; supported. ; Return Value(s): Returns packed string to be unpacked by _UnpackStrToVar() ; Author(s): Ben Brightwell ; ;=============================================================================== Func _PackVarToStr(ByRef $vPackVar) Local $iNumDims = UBound($vPackVar, 0) ; Number of dimensions of $vPackVar Local $sVarStr = "$[" & $iNumDims & "]$" ; Return string of packed variable Local $iCounter1 = "" ; Nested Counter Local $iCounter2 = "" ; Nested Counter Local $iCounter3 = "" ; Nested Counter Local $iCounter4 = "" ; Nested Counter For $i = 1 To $iNumDims $sVarStr &= "$[" & UBound($vPackVar, $i) & "]$" Next Select Case $iNumDims == 0 If $vPackVar == "" Then $sVarStr &= "<nil>" Else $sVarStr &= $vPackVar EndIf Case $iNumDims == 1 For $iCounter1 = 0 To UBound($vPackVar, 1) - 1 If $vPackVar[$iCounter1] == "" And UBound($vPackVar[$iCounter1], 0) == 0 Then $sVarStr &= "$[0]$<nil>" Else $sVarStr &= _PackVarToStr($vPackVar[$iCounter1]) EndIf Next Case $iNumDims == 2 For $iCounter1 = 0 To UBound($vPackVar, 1) - 1 For $iCounter2 = 0 To UBound($vPackVar, 2) - 1 If $vPackVar[$iCounter1][$iCounter2] == "" And UBound($vPackVar[$iCounter1][$iCounter2], 0) == 0 Then $sVarStr &= "$[0]$<nil>" Else $sVarStr &= _PackVarToStr($vPackVar[$iCounter1][$iCounter2]) EndIf Next Next Case $iNumDims == 3 For $iCounter1 = 0 To UBound($vPackVar, 1) - 1 For $iCounter2 = 0 To UBound($vPackVar, 2) - 1 For $iCounter3 = 0 To UBound($vPackVar, 3) - 1 If $vPackVar[$iCounter1][$iCounter2][$iCounter3] == "" And UBound($vPackVar[$iCounter1][$iCounter2][$iCounter3], 0) == 0 Then $sVarStr &= "$[0]$<nil>" Else $sVarStr &= _PackVarToStr($vPackVar[$iCounter1][$iCounter2][$iCounter3]) EndIf Next Next Next Case $iNumDims == 4 For $iCounter1 = 0 To UBound($vPackVar, 1) - 1 For $iCounter2 = 0 To UBound($vPackVar, 2) - 1 For $iCounter3 = 0 To UBound($vPackVar, 3) - 1 For $iCounter4 = 0 To UBound($vPackVar, 4) - 1 If $vPackVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4] == "" And UBound($vPackVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4], 0) == 0 Then $sVarStr &= "$[0]$<nil>" Else $sVarStr &= _PackVarToStr($vPackVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4]) EndIf Next Next Next Next EndSelect Return $sVarStr EndFunc ;==>_PackVarToStr ;=============================================================================== ; ; Function Name: _LineIsFunction() ; Description: Classifies the given line as either the start/end of a function, or as a regular line. ; Uses regular expressions to match every possible scenario. ; Parameter(s): $vLine = The string to be classified. ; Return Value(s): On Success - 1, this line is the start/end of a function. Sets @Error to: ; 1 - Line is the start of a function ; 2 - Line is the end of a function ; On Failure - 0, this line isn't a function. ; Author(s): Chris H. (darkthorn) ; ;=============================================================================== Func _LineIsFunction($vLine) ; Classify the type of line. First check if this line is an EndFunc. If StringRegExp($vLine, "^\s*(?i:EndFunc)", 0) Then ; Success. Pattern Matched. This is the end of a function. SetError(2) ; line is endfunc Return 1 ; success Else ; Failure. Pattern not matched. This is not the end of a function. So let's check if it's the start of a function. If StringRegExp($vLine, "^\s*(?i:Func)\s+\S+\s*\(.*\)", 0) Then ; Success. Pattern Matched. This is the start of a function. SetError(1) ; line is func Return 1 ; success Else ; Failure. Pattern not matched. Since this wasn't the start of a function either, treat it as a normal line. SetError(0) ; line isn't function Return 0 ; failure EndIf EndIf EndFunc ;==>_LineIsFunction ;=============================================================================== ; ; Function Name: _RandomFileName() ; Description: Generates a random file name in the working directory so that ; the a filename is not repeated for up to 10000 coroutine ; scripts per main script. ; Parameter(s): none ; Return Value(s): FileGetShortName-converted string representing the full path ; to the temporary file, including the .au3 extension ; Author(s): Ben Brightwell ; ;=============================================================================== Func _RandomFileName() $name = FileGetShortName($sWorkingDir) & "\" & StringTrimRight(@ScriptName, 4) & Random(0, 10000, 1) & ".au3" $found = 0 For $i = 1 To $avCoThreads[0][0] If $name == $avCoThreads[$i][0] Then $found = 1 EndIf Next While $found == 1 $found = 0 $name = FileGetShortName($sWorkingDir) & "\" & StringTrimRight(@ScriptName, 4) & Random(0, 10000, 1) & ".au3" For $i = 1 To $avCoThreads[0][0] If $name == $avCoThreads[$i][0] Then $found = 1 EndIf Next WEnd Return $name EndFunc ;==>_RandomFileName Edited July 12, 2010 by ParoXsitiC Marcelos 1 Link to comment Share on other sites More sharing options...
ParoXsitiC Posted July 13, 2010 Share Posted July 13, 2010 Ok, so I lied. I tested it with the included "Arrays.au3" Located here:expandcollapse popup#include "Coroutine.au3" HotKeySet("{END}", "_exit") ;Just setting up the test array Dim $testarray[5] Dim $sub1[8] $sub1[0] = "test1" $sub1[1] = "test2" $sub1[2] = "test3" $sub1[3] = "test4" $sub1[4] = "test5" $sub1[5] = "test6" $sub1[6] = "test7" $sub1[7] = "test8" Dim $sub2[8] $sub2[0] = "Elements can hold strings" $sub2[1] = "with spaces " $sub2[2] = "and punctuation.!@#$%^&*()" $sub2[3] = "Elements can also be null" $sub2[4] = "" $sub2[5] = "" $sub2[6] = "End of" $sub2[7] = "sub2 array" $testarray[0] = "Beginning of Main Array" $testarray[1] = "Contains 2 nested arrays" $testarray[2] = $sub1 ;$testarray[3] = $sub2 ... $sub2 will be placed here in the thread and passed back $testarray[4] = "End of Main Array" ;Creates the thread using the default delimiter "|" and stores the thread ID in $thread $thread = _CoCreate('Func function($arr1, $arr2)|$arr1[3] = $arr2|Return $arr1|EndFunc') ;Starts an instance of the thread $pid = _CoStart($thread, '$testarray, $sub2') ;This loop waits until the coroutine returns whatever it's supposed to return, then displays the results using ; another UDF I created: _ArrayToDisplayString() which handles up to 4-dimensional arrays and nested arrays While 1 If _CoStatus($pid) == "returned" Then MsgBox(0,"Main Thread", _ArrayToDisplayString(_CoGetReturn($pid))) ExitLoop EndIf Sleep(10) WEnd ;This must be called to clean up the temp files that were created with _CoCreate() _CoCleanup() Func _exit() Exit EndFunc ;=============================================================================== ; ; Function Name: _ArrayToDisplayString() ; Description: Converts an Array of up to 4 dimensions into a string ; displaying the contents of the array. ; NOTE: now supports nested arrays ; Parameter(s): $vDispVar - Array to convert ; $iStyle[optional] - 0 = Cascading style (Default) ; $iLevel - used for recursion, DO NOT CHANGE ; Return Value(s): If array is passed - String representing array ; If non-array is passed - String representing variable ; Author(s): Ben Brightwell ; ;=============================================================================== Func _ArrayToDisplayString($vDispVar, $iStyle = 0, $iLevel = 0) If $iStyle <> 0 And $iStyle <> 1 Then $iStyle = 0 EndIf $iNumDims = UBound($vDispVar, 0) ; Number of dimensions of $vDispVar Local $sDisplayStr = "" Local $iDimCounter = "" ; Main Dimension Counter Local $iCounter1 = "" ; Nested Counter Local $iCounter2 = "" ; Nested Counter Local $iCounter3 = "" ; Nested Counter Local $iCounter4 = "" ; Nested Counter Select Case $iNumDims == 1 For $iCounter1 = 0 To UBound($vDispVar, 1) - 1 If $iLevel > 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next EndIf If IsArray($vDispVar[$iCounter1]) Then $sDisplayStr &= "[" & $iCounter1 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter1 & "]= " EndIf $sDisplayStr &= _ArrayToDisplayString($vDispVar[$iCounter1], $iStyle, $iLevel+1) Next Case $iNumDims == 2 For $iCounter1 = 0 To UBound($vDispVar, 1) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= "[" & $iCounter1 & "]= " & @CRLF EndIf For $iCounter2 = 0 To UBound($vDispVar, 2) - 1 If $iStyle == 0 Then $sDisplayStr &= " " EndIf If $iLevel > 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next EndIf If $iStyle = 0 Then If IsArray($vDispVar[$iCounter1][$iCounter2]) Then $sDisplayStr &= "[" & $iCounter2 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter2 & "]= " EndIf ElseIf $iStyle == 1 Then If IsArray($vDispVar[$iCounter1][$iCounter2]) Then $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "]= " EndIf EndIf $sDisplayStr &= _ArrayToDisplayString($vDispVar[$iCounter1][$iCounter2], $iStyle, $iLevel+1) Next Next Case $iNumDims == 3 For $iCounter1 = 0 To UBound($vDispVar, 1) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= "[" & $iCounter1 & "]= " & @CRLF EndIf For $iCounter2 = 0 To UBound($vDispVar, 2) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= " [" & $iCounter2 & "]= " & @CRLF EndIf For $iCounter3 = 0 To UBound($vDispVar, 3) - 1 If $iStyle == 0 Then $sDisplayStr &= " " EndIf If $iLevel > 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next EndIf If $iStyle == 0 Then If IsArray($vDispVar[$iCounter1][$iCounter2][$iCounter3]) Then $sDisplayStr &= "[" & $iCounter3 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter3 & "]= " EndIf ElseIf $iStyle == 1 Then If IsArray($vDispVar[$iCounter1][$iCounter2][$iCounter3]) Then $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "][" & $iCounter3 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "][" & $iCounter3 & "]= " EndIf EndIf $sDisplayStr &= _ArrayToDisplayString($vDispVar[$iCounter1][$iCounter2][$iCounter3], $iStyle, $iLevel+1) Next Next Next Case $iNumDims == 4 For $iCounter1 = 0 To UBound($vDispVar, 1) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= "[" & $iCounter1 & "]= " & @CRLF EndIf For $iCounter2 = 0 To UBound($vDispVar, 2) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= " [" & $iCounter2 & "]= " & @CRLF EndIf For $iCounter3 = 0 To UBound($vDispVar, 3) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= " [" & $iCounter3 & "]= " & @CRLF EndIf For $iCounter4 = 0 To UBound($vDispVar, 4) - 1 If $iStyle == 0 Then $sDisplayStr &= " " EndIf If $iLevel > 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next EndIf If $iStyle == 0 Then If IsArray($vDispVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4]) Then $sDisplayStr &= "[" & $iCounter4 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter4 & "]= " EndIf ElseIf $iStyle == 1 Then If IsArray($vDispVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4]) Then $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "][" & $iCounter3 & "][" & $iCounter4 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "][" & $iCounter3 & "][" & $iCounter4 & "]= " EndIf EndIf $sDisplayStr &= _ArrayToDisplayString($vDispVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4], $iStyle, $iLevel+1) Next Next Next Next EndSelect If $iNumDims == 0 Then $sDisplayStr &= $vDispVar & @CRLF EndIf Return $sDisplayStr EndFuncWhich seems to output fine. However, when I try to use example MultiDimensionalArrays.au3 Located here:expandcollapse popup#include "Coroutine.au3" HotKeySet("{END}", "_exit") ;Testing 1-Dimensional Array Dim $test1dim[2] $test1dim[0] = "test1" $test1dim[1] = "test2" ;Testing 2-Dimensional Array Dim $test2dim[2][2] $test2dim[0][0] = "test1" $test2dim[0][1] = "test2" $test2dim[1][0] = "test3" $test2dim[1][1] = "test4" ;Testing 3-Dimensional Array Dim $test3dim[2][2][2] $test3dim[0][0][0] = "test1" $test3dim[0][0][1] = "test2" $test3dim[0][1][0] = "test3" $test3dim[0][1][1] = "test4" $test3dim[1][0][0] = "test5" $test3dim[1][0][1] = "test6" $test3dim[1][1][0] = "test7" $test3dim[1][1][1] = "test8" ;Testing 4-Dimensional Array Dim $test4dim[3][2][2][2] $test4dim[0][0][0][0] = "test1" $test4dim[0][0][0][1] = "test2" $test4dim[0][0][1][0] = "test3" $test4dim[0][0][1][1] = "test4" $test4dim[0][1][0][0] = "test5" $test4dim[0][1][0][1] = "test6" $test4dim[0][1][1][0] = "test7" $test4dim[0][1][1][1] = "test8" $test4dim[1][0][0][0] = "test9" $test4dim[1][0][0][1] = "test0" $test4dim[1][0][1][0] = "test11" $test4dim[1][0][1][1] = "test12" $test4dim[1][1][0][0] = "test13" $test4dim[1][1][0][1] = "test14" $test4dim[1][1][1][0] = "test15" $test4dim[1][1][1][1] = "test16" $test4dim[2][0][0][0] = "test17" $test4dim[2][0][0][1] = "test18" $test4dim[2][0][1][0] = "test19" $test4dim[2][0][1][1] = "test20" $test4dim[2][1][0][0] = "test21" $test4dim[2][1][0][1] = "test22" $test4dim[2][1][1][0] = "test23" $test4dim[2][1][1][1] = "test24" ;Creates the thread using the default delimiter "|" and stores the thread ID in $thread $thread = _CoCreate('Func function($arr1)|Return $arr1|EndFunc') ;Starts an instance of the thread $pid1 = _CoStart($thread, '$test1dim') $pid2 = _CoStart($thread, '$test2dim') $pid3 = _CoStart($thread, '$test3dim') $pid4 = _CoStart($thread, '$test4dim') ;This loop waits until the coroutine returns whatever it's supposed to return, then displays the results using ; another UDF I created: _ArrayToDisplayString() which handles up to 4-dimensional arrays and nested arrays $numFinished = 0 While $numFinished < 4 If _CoStatus($pid1) == "returned" Then MsgBox(0,"1-Dimensional", _ArrayToDisplayString(_CoGetReturn($pid1))) $numFinished += 1 EndIf If _CoStatus($pid2) == "returned" Then MsgBox(0,"2-Dimensional", _ArrayToDisplayString(_CoGetReturn($pid2))) $numFinished += 1 EndIf If _CoStatus($pid3) == "returned" Then MsgBox(0,"3-Dimensional", _ArrayToDisplayString(_CoGetReturn($pid3))) $numFinished += 1 EndIf If _CoStatus($pid4) == "returned" Then MsgBox(0,"4-Dimensional", _ArrayToDisplayString(_CoGetReturn($pid4))) $numFinished += 1 EndIf Sleep(10) WEnd ;This must be called to clean up the temp files that were created with _CoCreate() _CoCleanup() Func _exit() Exit EndFunc ;=============================================================================== ; ; Function Name: _ArrayToDisplayString() ; Description: Converts an Array of up to 4 dimensions into a string ; displaying the contents of the array. ; NOTE: now supports nested arrays ; Parameter(s): $vDispVar - Array to convert ; $iStyle[optional] - 0 = Cascading style (Default) ; $iLevel - used for recursion, DO NOT CHANGE ; Return Value(s): If array is passed - String representing array ; If non-array is passed - String representing variable ; Author(s): Ben Brightwell ; ;=============================================================================== Func _ArrayToDisplayString($vDispVar, $iStyle = 0, $iLevel = 0) If $iStyle <> 0 And $iStyle <> 1 Then $iStyle = 0 EndIf $iNumDims = UBound($vDispVar, 0) ; Number of dimensions of $vDispVar Local $sDisplayStr = "" Local $iDimCounter = "" ; Main Dimension Counter Local $iCounter1 = "" ; Nested Counter Local $iCounter2 = "" ; Nested Counter Local $iCounter3 = "" ; Nested Counter Local $iCounter4 = "" ; Nested Counter Select Case $iNumDims == 1 For $iCounter1 = 0 To UBound($vDispVar, 1) - 1 If $iLevel > 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next EndIf If IsArray($vDispVar[$iCounter1]) Then $sDisplayStr &= "[" & $iCounter1 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter1 & "]= " EndIf $sDisplayStr &= _ArrayToDisplayString($vDispVar[$iCounter1], $iStyle, $iLevel+1) Next Case $iNumDims == 2 For $iCounter1 = 0 To UBound($vDispVar, 1) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= "[" & $iCounter1 & "]= " & @CRLF EndIf For $iCounter2 = 0 To UBound($vDispVar, 2) - 1 If $iStyle == 0 Then $sDisplayStr &= " " EndIf If $iLevel > 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next EndIf If $iStyle = 0 Then If IsArray($vDispVar[$iCounter1][$iCounter2]) Then $sDisplayStr &= "[" & $iCounter2 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter2 & "]= " EndIf ElseIf $iStyle == 1 Then If IsArray($vDispVar[$iCounter1][$iCounter2]) Then $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "]= " EndIf EndIf $sDisplayStr &= _ArrayToDisplayString($vDispVar[$iCounter1][$iCounter2], $iStyle, $iLevel+1) Next Next Case $iNumDims == 3 For $iCounter1 = 0 To UBound($vDispVar, 1) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= "[" & $iCounter1 & "]= " & @CRLF EndIf For $iCounter2 = 0 To UBound($vDispVar, 2) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= " [" & $iCounter2 & "]= " & @CRLF EndIf For $iCounter3 = 0 To UBound($vDispVar, 3) - 1 If $iStyle == 0 Then $sDisplayStr &= " " EndIf If $iLevel > 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next EndIf If $iStyle == 0 Then If IsArray($vDispVar[$iCounter1][$iCounter2][$iCounter3]) Then $sDisplayStr &= "[" & $iCounter3 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter3 & "]= " EndIf ElseIf $iStyle == 1 Then If IsArray($vDispVar[$iCounter1][$iCounter2][$iCounter3]) Then $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "][" & $iCounter3 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "][" & $iCounter3 & "]= " EndIf EndIf $sDisplayStr &= _ArrayToDisplayString($vDispVar[$iCounter1][$iCounter2][$iCounter3], $iStyle, $iLevel+1) Next Next Next Case $iNumDims == 4 For $iCounter1 = 0 To UBound($vDispVar, 1) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= "[" & $iCounter1 & "]= " & @CRLF EndIf For $iCounter2 = 0 To UBound($vDispVar, 2) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= " [" & $iCounter2 & "]= " & @CRLF EndIf For $iCounter3 = 0 To UBound($vDispVar, 3) - 1 If $iStyle == 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next $sDisplayStr &= " [" & $iCounter3 & "]= " & @CRLF EndIf For $iCounter4 = 0 To UBound($vDispVar, 4) - 1 If $iStyle == 0 Then $sDisplayStr &= " " EndIf If $iLevel > 0 Then For $i = 1 To $iLevel $sDisplayStr &= " " Next EndIf If $iStyle == 0 Then If IsArray($vDispVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4]) Then $sDisplayStr &= "[" & $iCounter4 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter4 & "]= " EndIf ElseIf $iStyle == 1 Then If IsArray($vDispVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4]) Then $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "][" & $iCounter3 & "][" & $iCounter4 & "]= " & @CRLF Else $sDisplayStr &= "[" & $iCounter1 & "][" & $iCounter2 & "][" & $iCounter3 & "][" & $iCounter4 & "]= " EndIf EndIf $sDisplayStr &= _ArrayToDisplayString($vDispVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4], $iStyle, $iLevel+1) Next Next Next Next EndSelect If $iNumDims == 0 Then $sDisplayStr &= $vDispVar & @CRLF EndIf Return $sDisplayStr EndFuncIt gives me weird and intermittent results. I am no programmer, my fixes just included little "hacks" to get it to work. Obviously im not doing something right. Here is an idea of the hacks I did, so that someone can understand;I changed all ConsoleRead(0,true) to ConsoleRead(true) When using $iNumChrsToRead = StringRegExp($sParamsInStr, "(\d*?)(\#)(?:\$\[)", 1) I understood the supposed 2nd match was a length of the first match, there I changed it to $iNumChrsToRead= StringRegExp($sParamsInStr, "(\d*?)(?:\$\[)", 1) and instead of using the old $iNumChrsToRead[1] I would use StringInStr($sParamsInStr, $iNumChrsToRead[0]) + StringLen ( $iNumChrsToRead[0] ) - 1Regexs like (?i:return[:space:]*) gave me an error so i replaced them with (?i:return\s*)$asParams = StringRegExp($sParamStr, '(".*?".*?,|[^ ]*?[ ]?,)*', 3) changed to $asParams = StringRegExp($sParamStr, '(".*?".*?,|[^ ]*?[ ]?,)+', 3) ..... I forgot why.Occurrence of things like StdoutRead($iPID, 5, True) where it seemed the old function means to take the first 5 chars from the left, was changed to StringLeft(StdoutRead($iPID, True), 5) ...... I think there is where my problem is, because he has IF statements like: If StdoutRead($iPID, 0, True) <> 0 Then ... and StringLeft(StdoutRead($iPID, True), 0) wouldnt make sense there....Anyways... I am noob, will someone who knows what they are doing please take my notes and turn Coroutine 1.1.0 Found here: download into a working model on today's autoit Link to comment Share on other sites More sharing options...
ParoXsitiC Posted July 13, 2010 Share Posted July 13, 2010 (edited) As I guessed it was StdoutRead...I suppose the old StdoutRead if you had StdoutRead($iPID, 0, True) then it was checking if it was done reading... So I changed it from If StdoutRead($iPID, 0, True) <> 0 Then to StdoutRead($iPID) $StdoutReadIsDone = @error If $StdoutReadIsDone ThenI am not sure how to do If StringLeft(StdoutRead($iPID, True), 0) > 5 Then for yielding.Does autoit have old documentation anywhere? Edited July 13, 2010 by ParoXsitiC Link to comment Share on other sites More sharing options...
Marcelos Posted September 15, 2013 Share Posted September 15, 2013 (edited) Hi, Neogia, Ben Brightwell, ChrisL. & ParoXsitiC I expect I don’t miss to name the authors of this solution. (just let me know) Its wonderful!! Thanks Anyways I think there is needed to explain how to use this multitreading solution. Today ill explain the basics.(I spent more than 4 hours to figure out how to use it). Im sure that there are some things that I miss, but . this works for me. I used the code for Coroutine.au3 1.1.1 . published in the forum by ParoXsitiC at http://www.autoitscript.com/forum/topic/23545-coroutine-multithreading-udf-library/?p=815988 ; File: Coroutine.au3 ; Description: UDF Library used for coroutine multithreading ; Version: 1.1.1 ; Date: 8/13/07 1. Write your code that you want to run as a tread, as a function. a. I didn’t test yet, having in the function calls for other functions ( this is for the next post) 2.Use the code FormatCoCreate.au3 to prepeare the tread function this is the code i used ( i dont like the extra white lines that the original script creates) a. run the FormatCoCreate.au3 . b. select the function for the tread c: use the keys CRTL + SHIFT + C d. the code will be formated for the use with corutine ( this is every line is ended by a delimiter ( in this case , the pipe symbol) expandcollapse popupHotKeySet("^+c", "_FormatCoCreate") HotKeySet("{END}", "_exit") While 1 Sleep(50) WEnd Func _FormatCoCreate() Send("^c") Sleep(500) $rawText = ClipGet() If StringInStr($rawText, "$[") Then MsgBox(0,"Error","Function cannot contain the special delimiter: $[" & @CRLF & "Please replace text and try again.") EndIf If StringInStr($rawText, "|") Then If StringInStr($rawText, "~{[]}~") Then $delim = InputBox('Input custom delimiter, as both "|" and "~{[]}~" exist in your function', "Delimiter") Else $delim = "~{[]}~" EndIf Else $delim = "|" EndIf ;~ $replacedText = StringReplace($rawText, @CRLF, $delim) $replacedText = "" $splitText = StringSplit($rawText, @CRLF) For $lineCount = 1 To $splitText[0] $textParts = StringRegExp($splitText[$lineCount], '(\s*)(.*)', 1) If IsArray($textParts) And UBound($textParts) == 2 Then if $textParts[1]<>"" then ;to eliminar las lineas blancas $replacedText &= $textParts[0] & "'" & $textParts[1] & $delim & "'" If $lineCount <> $splitText[0] Then $replacedText &= " & _" & @CRLF EndIf endif ;to eliminar las lineas blancas ElseIf IsArray($textParts) And UBound($textParts) == 1 Then $replacedText &= "'" & $textParts[0] & $delim & "'" If $lineCount <> $splitText[0] Then $replacedText &= " & _" & @CRLF EndIf EndIf Next If $delim <> "|" Then $setText = '$ThreadName = _CoCreate(' & $replacedText & ', ''' & $delim & ''')' Else $setText = '$YourThreadNameHere = _CoCreate(' & $replacedText & ')' EndIf ClipPut($setText) Send("^v") EndFunc Func _exit() Exit EndFunc 3. copy the prepared code to a new file (in this example Tread.au3) a. ( this file will be included in your code) b. Ex. $ThreadName = _CoCreate (your code) 4. In this new file Tread.au3 , add the _CoInclude command to add all the includes you nned a. Every UDF must be included b. EX. _CoInclude($ThreadName,"#include <WinAPI.au3>") 5. In the new file Tread.au3 ,add the _CoStart function to start the tread a. EX. $Threadpid = _CoStart($LynckThreadName, '') 6. Back to your Script a. Add the #include <Coroutine.au3> b. Add the #include <Tread.au3> to call the tread an start it. 7. You can monitor the tread activity status from your main code. ConsoleWrite("!!!!" & _CoStatus($Threadpid) & @crlf) If _CoStatus($LynckThreadpid) == "returned" Then ConsoleWrite(">>>>" & _CoStatus(Threadpid) & @crlf) _CoCleanup() endif I keep working on the use of this Coroutine UDF , and i post my findings. i ll expect this helps you Thanks again for the great solution. Edited September 15, 2013 by Marcelos Graphical Control - Week Planner Link to comment Share on other sites More sharing options...
TheSaint Posted September 15, 2013 Share Posted September 15, 2013 @Marcelos - Welcome to the forum. I guess your deliberations, code, etc might help someone, but you may not have noticed, that the last update to this UDF was early 2006. The OP hasn't been active here in about 3 years and some of the others (maybe all) haven't been around for some time. So it is possible, that with newer versions of AutoIt since then, that there may be more current/better similar UDF's out there? Cheers! Make sure brain is in gear before opening mouth! Remember, what is not said, can be just as important as what is said. Spoiler What is the Secret Key? Life is like a Donut If I put effort into communication, I expect you to read properly & fully, or just not comment. Ignoring those who try to divert conversation with irrelevancies. If I'm intent on insulting you or being rude, I will be obvious, not ambiguous about it. I'm only big and bad, to those who have an over-active imagination. I may have the Artistic Liesense to disagree with you. TheSaint's Toolbox (be advised many downloads are not working due to ISP screwup with my storage) Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now