multi/changes.html
Ryan Ward a07fe49880 Updated to 1.10.0!
Check changes.md for what was done
2018-05-31 22:48:14 -04:00

869 lines
99 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>changes.html</title>
<meta name="generator" content="Haroopad 0.13.1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>div.oembedall-githubrepos{border:1px solid #DDD;border-radius:4px;list-style-type:none;margin:0 0 10px;padding:8px 10px 0;font:13.34px/1.4 helvetica,arial,freesans,clean,sans-serif;width:452px;background-color:#fff}div.oembedall-githubrepos .oembedall-body{background:-moz-linear-gradient(center top,#FAFAFA,#EFEFEF);background:-webkit-gradient(linear,left top,left bottom,from(#FAFAFA),to(#EFEFEF));border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-top:1px solid #EEE;margin-left:-10px;margin-top:8px;padding:5px 10px;width:100%}div.oembedall-githubrepos h3{font-size:14px;margin:0;padding-left:18px;white-space:nowrap}div.oembedall-githubrepos p.oembedall-description{color:#444;font-size:12px;margin:0 0 3px}div.oembedall-githubrepos p.oembedall-updated-at{color:#888;font-size:11px;margin:0}div.oembedall-githubrepos ul.oembedall-repo-stats{border:none;float:right;font-size:11px;font-weight:700;padding-left:15px;position:relative;z-index:5;margin:0}div.oembedall-githubrepos ul.oembedall-repo-stats li{border:none;color:#666;display:inline-block;list-style-type:none;margin:0!important}div.oembedall-githubrepos ul.oembedall-repo-stats li a{background-color:transparent;border:none;color:#666!important;background-position:5px -2px;background-repeat:no-repeat;border-left:1px solid #DDD;display:inline-block;height:21px;line-height:21px;padding:0 5px 0 23px}div.oembedall-githubrepos ul.oembedall-repo-stats li:first-child a{border-left:medium none;margin-right:-3px}div.oembedall-githubrepos ul.oembedall-repo-stats li a:hover{background:5px -27px no-repeat #4183C4;color:#FFF!important;text-decoration:none}div.oembedall-githubrepos ul.oembedall-repo-stats li:first-child a:hover{border-bottom-left-radius:3px;border-top-left-radius:3px}ul.oembedall-repo-stats li:last-child a:hover{border-bottom-right-radius:3px;border-top-right-radius:3px}span.oembedall-closehide{background-color:#aaa;border-radius:2px;cursor:pointer;margin-right:3px}div.oembedall-container{margin-top:5px;text-align:left}.oembedall-ljuser{font-weight:700}.oembedall-ljuser img{vertical-align:bottom;border:0;padding-right:1px}.oembedall-stoqembed{border-bottom:1px dotted #999;float:left;overflow:hidden;width:730px;line-height:1;background:#FFF;color:#000;font-family:Arial,Liberation Sans,DejaVu Sans,sans-serif;font-size:80%;text-align:left;margin:0;padding:0}.oembedall-stoqembed a{color:#07C;text-decoration:none;margin:0;padding:0}.oembedall-stoqembed a:hover{text-decoration:underline}.oembedall-stoqembed a:visited{color:#4A6B82}.oembedall-stoqembed h3{font-family:Trebuchet MS,Liberation Sans,DejaVu Sans,sans-serif;font-size:130%;font-weight:700;margin:0;padding:0}.oembedall-stoqembed .oembedall-reputation-score{color:#444;font-size:120%;font-weight:700;margin-right:2px}.oembedall-stoqembed .oembedall-user-info{height:35px;width:185px}.oembedall-stoqembed .oembedall-user-info .oembedall-user-gravatar32{float:left;height:32px;width:32px}.oembedall-stoqembed .oembedall-user-info .oembedall-user-details{float:left;margin-left:5px;overflow:hidden;white-space:nowrap;width:145px}.oembedall-stoqembed .oembedall-question-hyperlink{font-weight:700}.oembedall-stoqembed .oembedall-stats{background:#EEE;margin:0 0 0 7px;padding:4px 7px 6px;width:58px}.oembedall-stoqembed .oembedall-statscontainer{float:left;margin-right:8px;width:86px}.oembedall-stoqembed .oembedall-votes{color:#555;padding:0 0 7px;text-align:center}.oembedall-stoqembed .oembedall-vote-count-post{font-size:240%;color:#808185;display:block;font-weight:700}.oembedall-stoqembed .oembedall-views{color:#999;padding-top:4px;text-align:center}.oembedall-stoqembed .oembedall-status{margin-top:-3px;padding:4px 0;text-align:center;background:#75845C;color:#FFF}.oembedall-stoqembed .oembedall-status strong{color:#FFF;display:block;font-size:140%}.oembedall-stoqembed .oembedall-summary{float:left;width:635px}.oembedall-stoqembed .oembedall-excerpt{line-height:1.2;margin:0;padding:0 0 5px}.oembedall-stoqembed .oembedall-tags{float:left;line-height:18px}.oembedall-stoqembed .oembedall-tags a:hover{text-decoration:none}.oembedall-stoqembed .oembedall-post-tag{background-color:#E0EAF1;border-bottom:1px solid #3E6D8E;border-right:1px solid #7F9FB6;color:#3E6D8E;font-size:90%;line-height:2.4;margin:2px 2px 2px 0;padding:3px 4px;text-decoration:none;white-space:nowrap}.oembedall-stoqembed .oembedall-post-tag:hover{background-color:#3E6D8E;border-bottom:1px solid #37607D;border-right:1px solid #37607D;color:#E0EAF1}.oembedall-stoqembed .oembedall-fr{float:right}.oembedall-stoqembed .oembedall-statsarrow{background-image:url(http://cdn.sstatic.net/stackoverflow/img/sprites.png?v=3);background-repeat:no-repeat;overflow:hidden;background-position:0 -435px;float:right;height:13px;margin-top:12px;width:7px}.oembedall-facebook1{border:1px solid #1A3C6C;padding:0;font:13.34px/1.4 verdana;width:500px}.oembedall-facebook2{background-color:#627add}.oembedall-facebook2 a{color:#e8e8e8;text-decoration:none}.oembedall-facebookBody{background-color:#fff;vertical-align:top;padding:5px}.oembedall-facebookBody .contents{display:inline-block;width:100%}.oembedall-facebookBody div img{float:left;margin-right:5px}div.oembedall-lanyard{-webkit-box-shadow:none;-webkit-transition-delay:0s;-webkit-transition-duration:.4000000059604645s;-webkit-transition-property:width;-webkit-transition-timing-function:cubic-bezier(0.42,0,.58,1);background-attachment:scroll;background-clip:border-box;background-color:transparent;background-image:none;background-origin:padding-box;border-width:0;box-shadow:none;color:#112644;display:block;float:left;font-family:'Trebuchet MS',Trebuchet,sans-serif;font-size:16px;height:253px;line-height:19px;margin:0;max-width:none;min-height:0;outline:#112644 0;overflow-x:visible;overflow-y:visible;padding:0;position:relative;text-align:left;vertical-align:baseline;width:804px}div.oembedall-lanyard .tagline{font-size:1.5em}div.oembedall-lanyard .wrapper{overflow:hidden;clear:both}div.oembedall-lanyard .split{float:left;display:inline}div.oembedall-lanyard .prominent-place .flag:active,div.oembedall-lanyard .prominent-place .flag:focus,div.oembedall-lanyard .prominent-place .flag:hover,div.oembedall-lanyard .prominent-place .flag:link,div.oembedall-lanyard .prominent-place .flag:visited{float:left;display:block;width:48px;height:48px;position:relative;top:-5px;margin-right:10px}div.oembedall-lanyard .place-context{font-size:.889em}div.oembedall-lanyard .prominent-place .sub-place{display:block}div.oembedall-lanyard .prominent-place{font-size:1.125em;line-height:1.1em;font-weight:400}div.oembedall-lanyard .main-date{color:#8CB4E0;font-weight:700;line-height:1.1}div.oembedall-lanyard .first{width:48.57%;margin:0 0 0 2.857%}.mermaid .label{color:#333}.node circle,.node polygon,.node rect{fill:#cde498;stroke:#13540c;stroke-width:1px}.edgePath .path{stroke:green;stroke-width:1.5px}.cluster rect{fill:#cdffb2;rx:40;stroke:#6eaa49;stroke-width:1px}.cluster text{fill:#333}.actor{stroke:#13540c;fill:#cde498}text.actor{fill:#000;stroke:none}.actor-line{stroke:grey}.messageLine0{stroke-width:1.5;stroke-dasharray:"2 2";marker-end:"url(#arrowhead)";stroke:#333}.messageLine1{stroke-width:1.5;stroke-dasharray:"2 2";stroke:#333}#arrowhead{fill:#333}#crosshead path{fill:#333!important;stroke:#333!important}.messageText{fill:#333;stroke:none}.labelBox{stroke:#326932;fill:#cde498}.labelText,.loopText{fill:#000;stroke:none}.loopLine{stroke-width:2;stroke-dasharray:"2 2";marker-end:"url(#arrowhead)";stroke:#326932}.note{stroke:#6eaa49;fill:#fff5ad}.noteText{fill:#000;stroke:none;font-family:'trebuchet ms',verdana,arial;font-size:14px}.section{stroke:none;opacity:.2}.section0,.section2{fill:#6eaa49}.section1,.section3{fill:#fff;opacity:.2}.sectionTitle0,.sectionTitle1,.sectionTitle2,.sectionTitle3{fill:#333}.sectionTitle{text-anchor:start;font-size:11px;text-height:14px}.grid .tick{stroke:lightgrey;opacity:.3;shape-rendering:crispEdges}.grid path{stroke-width:0}.today{fill:none;stroke:red;stroke-width:2px}.task{stroke-width:2}.taskText{text-anchor:middle;font-size:11px}.taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px}.taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}.taskText0,.taskText1,.taskText2,.taskText3{fill:#fff}.task0,.task1,.task2,.task3{fill:#487e3a;stroke:#13540c}.taskTextOutside0,.taskTextOutside1,.taskTextOutside2,.taskTextOutside3{fill:#000}.active0,.active1,.active2,.active3{fill:#cde498;stroke:#13540c}.activeText0,.activeText1,.activeText2,.activeText3{fill:#000!important}.done0,.done1,.done2,.done3{stroke:grey;fill:lightgrey;stroke-width:2}.doneText0,.doneText1,.doneText2,.doneText3{fill:#000!important}.crit0,.crit1,.crit2,.crit3{stroke:#f88;fill:red;stroke-width:2}.activeCrit0,.activeCrit1,.activeCrit2,.activeCrit3{stroke:#f88;fill:#cde498;stroke-width:2}.doneCrit0,.doneCrit1,.doneCrit2,.doneCrit3{stroke:#f88;fill:lightgrey;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}.activeCritText0,.activeCritText1,.activeCritText2,.activeCritText3,.doneCritText0,.doneCritText1,.doneCritText2,.doneCritText3{fill:#000!important}.titleText{text-anchor:middle;font-size:18px;fill:#000}text{font-family:'trebuchet ms',verdana,arial;font-size:14px}html{height:100%}body{margin:0!important;padding:5px 20px 26px!important;background-color:#fff;font-family:"Lucida Grande","Segoe UI","Apple SD Gothic Neo","Malgun Gothic","Lucida Sans Unicode",Helvetica,Arial,sans-serif;font-size:.9em;overflow-x:hidden;overflow-y:auto}br,h1,h2,h3,h4,h5,h6{clear:both}hr.page{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x;border:0;height:3px;padding:0}hr.underscore{border-top-style:dashed!important}body >:first-child{margin-top:0!important}img.plugin{box-shadow:0 1px 3px rgba(0,0,0,.1);border-radius:3px}iframe{border:0}figure{-webkit-margin-before:0;-webkit-margin-after:0;-webkit-margin-start:0;-webkit-margin-end:0}kbd{border:1px solid #aaa;-moz-border-radius:2px;-webkit-border-radius:2px;border-radius:2px;-moz-box-shadow:1px 2px 2px #ddd;-webkit-box-shadow:1px 2px 2px #ddd;box-shadow:1px 2px 2px #ddd;background-color:#f9f9f9;background-image:-moz-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:-o-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:-webkit-linear-gradient(top,#eee,#f9f9f9,#eee);background-image:linear-gradient(top,#eee,#f9f9f9,#eee);padding:1px 3px;font-family:inherit;font-size:.85em}.oembeded .oembed_photo{display:inline-block}img[data-echo]{margin:25px 0;width:100px;height:100px;background:url(../img/ajax.gif) center center no-repeat #fff}.spinner{display:inline-block;width:10px;height:10px;margin-bottom:-.1em;border:2px solid rgba(0,0,0,.5);border-top-color:transparent;border-radius:100%;-webkit-animation:spin 1s infinite linear;animation:spin 1s infinite linear}.spinner:after{content:'';display:block;width:0;height:0;position:absolute;top:-6px;left:0;border:4px solid transparent;border-bottom-color:rgba(0,0,0,.5);-webkit-transform:rotate(45deg);transform:rotate(45deg)}@-webkit-keyframes spin{to{-webkit-transform:rotate(360deg)}}@keyframes spin{to{transform:rotate(360deg)}}p.toc{margin:0!important}p.toc ul{padding-left:10px}p.toc>ul{padding:10px;margin:0 10px;display:inline-block;border:1px solid #ededed;border-radius:5px}p.toc li,p.toc ul{list-style-type:none}p.toc li{width:100%;padding:0;overflow:hidden}p.toc li a::after{content:"."}p.toc li a:before{content:"• "}p.toc h5{text-transform:uppercase}p.toc .title{float:left;padding-right:3px}p.toc .number{margin:0;float:right;padding-left:3px;background:#fff;display:none}input.task-list-item{margin-left:-1.62em}.markdown{font-family:"Hiragino Sans GB","Microsoft YaHei",STHeiti,SimSun,"Lucida Grande","Lucida Sans Unicode","Lucida Sans",'Segoe UI',AppleSDGothicNeo-Medium,'Malgun Gothic',Verdana,Tahoma,sans-serif;padding:20px}.markdown a{text-decoration:none;vertical-align:baseline}.markdown a:hover{text-decoration:underline}.markdown h1{font-size:2.2em;font-weight:700;margin:1.5em 0 1em}.markdown h2{font-size:1.8em;font-weight:700;margin:1.275em 0 .85em}.markdown h3{font-size:1.6em;font-weight:700;margin:1.125em 0 .75em}.markdown h4{font-size:1.4em;font-weight:700;margin:.99em 0 .66em}.markdown h5{font-size:1.2em;font-weight:700;margin:.855em 0 .57em}.markdown h6{font-size:1em;font-weight:700;margin:.75em 0 .5em}.markdown h1+p,.markdown h1:first-child,.markdown h2+p,.markdown h2:first-child,.markdown h3+p,.markdown h3:first-child,.markdown h4+p,.markdown h4:first-child,.markdown h5+p,.markdown h5:first-child,.markdown h6+p,.markdown h6:first-child{margin-top:0}.markdown hr{border:1px solid #ccc}.markdown p{margin:1em 0;word-wrap:break-word}.markdown ol{list-style-type:decimal}.markdown li{display:list-item;line-height:1.4em}.markdown blockquote{margin:1em 20px}.markdown blockquote>:first-child{margin-top:0}.markdown blockquote>:last-child{margin-bottom:0}.markdown blockquote cite:before{content:'\2014 \00A0'}.markdown .code{border-radius:3px;word-wrap:break-word}.markdown pre{border-radius:3px;word-wrap:break-word;border:1px solid #ccc;overflow:auto;padding:.5em}.markdown pre code{border:0;display:block}.markdown pre>code{font-family:Consolas,Inconsolata,Courier,monospace;font-weight:700;white-space:pre;margin:0}.markdown code{border-radius:3px;word-wrap:break-word;border:1px solid #ccc;padding:0 5px;margin:0 2px}.markdown img{max-width:100%}.markdown mark{color:#000;background-color:#fcf8e3}.markdown table{padding:0;border-collapse:collapse;border-spacing:0;margin-bottom:16px}.markdown table tr td,.markdown table tr th{border:1px solid #ccc;margin:0;padding:6px 13px}.markdown table tr th{font-weight:700}.markdown table tr th>:first-child{margin-top:0}.markdown table tr th>:last-child{margin-bottom:0}.markdown table tr td>:first-child{margin-top:0}.markdown table tr td>:last-child{margin-bottom:0}@import url(http://fonts.googleapis.com/css?family=Roboto+Condensed:300italic,400italic,700italic,400,300,700);.haroopad{padding:20px;color:#222;font-size:15px;font-family:"Roboto Condensed",Tauri,"Hiragino Sans GB","Microsoft YaHei",STHeiti,SimSun,"Lucida Grande","Lucida Sans Unicode","Lucida Sans",'Segoe UI',AppleSDGothicNeo-Medium,'Malgun Gothic',Verdana,Tahoma,sans-serif;background:#fff;line-height:1.6;-webkit-font-smoothing:antialiased}.haroopad a{color:#3269a0}.haroopad a:hover{color:#4183c4}.haroopad h2{border-bottom:1px solid #e6e6e6}.haroopad h6{color:#777}.haroopad hr{border:1px solid #e6e6e6}.haroopad blockquote>code,.haroopad h1>code,.haroopad h2>code,.haroopad h3>code,.haroopad h4>code,.haroopad h5>code,.haroopad h6>code,.haroopad li>code,.haroopad p>code,.haroopad td>code{font-family:Consolas,"Liberation Mono",Menlo,Courier,monospace;font-size:85%;background-color:rgba(0,0,0,.02);padding:.2em .5em;border:1px solid #efefef}.haroopad pre>code{font-size:1em;letter-spacing:-1px;font-weight:700}.haroopad blockquote{border-left:4px solid #e6e6e6;padding:0 15px;color:#777}.haroopad table{background-color:#fafafa}.haroopad table tr td,.haroopad table tr th{border:1px solid #e6e6e6}.haroopad table tr:nth-child(2n){background-color:#f2f2f2}.hljs{display:block;overflow-x:auto;padding:.5em;background:#fdf6e3;color:#657b83;-webkit-text-size-adjust:none}.diff .hljs-header,.hljs-comment,.hljs-doctype,.hljs-javadoc,.hljs-pi,.lisp .hljs-string{color:#93a1a1}.css .hljs-tag,.hljs-addition,.hljs-keyword,.hljs-request,.hljs-status,.hljs-winutils,.method,.nginx .hljs-title{color:#859900}.hljs-command,.hljs-dartdoc,.hljs-hexcolor,.hljs-link_url,.hljs-number,.hljs-phpdoc,.hljs-regexp,.hljs-rules .hljs-value,.hljs-string,.hljs-tag .hljs-value,.tex .hljs-formula{color:#2aa198}.css .hljs-function,.hljs-built_in,.hljs-chunk,.hljs-decorator,.hljs-id,.hljs-identifier,.hljs-localvars,.hljs-title,.vhdl .hljs-literal{color:#268bd2}.hljs-attribute,.hljs-class .hljs-title,.hljs-constant,.hljs-link_reference,.hljs-parent,.hljs-type,.hljs-variable,.lisp .hljs-body,.smalltalk .hljs-number{color:#b58900}.css .hljs-pseudo,.diff .hljs-change,.hljs-attr_selector,.hljs-cdata,.hljs-header,.hljs-pragma,.hljs-preprocessor,.hljs-preprocessor .hljs-keyword,.hljs-shebang,.hljs-special,.hljs-subst,.hljs-symbol,.hljs-symbol .hljs-string{color:#cb4b16}.hljs-deletion,.hljs-important{color:#dc322f}.hljs-link_label{color:#6c71c4}.tex .hljs-formula{background:#eee8d5}.MathJax_Hover_Frame{border-radius:.25em;-webkit-border-radius:.25em;-moz-border-radius:.25em;-khtml-border-radius:.25em;box-shadow:0 0 15px #83A;-webkit-box-shadow:0 0 15px #83A;-moz-box-shadow:0 0 15px #83A;-khtml-box-shadow:0 0 15px #83A;border:1px solid #A6D!important;display:inline-block;position:absolute}.MathJax_Hover_Arrow{position:absolute;width:15px;height:11px;cursor:pointer}#MathJax_About{position:fixed;left:50%;width:auto;text-align:center;border:3px outset;padding:1em 2em;background-color:#DDD;color:#000;cursor:default;font-family:message-box;font-size:120%;font-style:normal;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;z-index:201;border-radius:15px;-webkit-border-radius:15px;-moz-border-radius:15px;-khtml-border-radius:15px;box-shadow:0 10px 20px gray;-webkit-box-shadow:0 10px 20px gray;-moz-box-shadow:0 10px 20px gray;-khtml-box-shadow:0 10px 20px gray;filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')}.MathJax_Menu{position:absolute;background-color:#fff;color:#000;width:auto;padding:2px;border:1px solid #CCC;margin:0;cursor:default;font:menu;text-align:left;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;z-index:201;box-shadow:0 10px 20px gray;-webkit-box-shadow:0 10px 20px gray;-moz-box-shadow:0 10px 20px gray;-khtml-box-shadow:0 10px 20px gray;filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')}.MathJax_MenuItem{padding:2px 2em;background:0 0}.MathJax_MenuArrow{position:absolute;right:.5em;color:#666}.MathJax_MenuActive .MathJax_MenuArrow{color:#fff}.MathJax_MenuArrow.RTL{left:.5em;right:auto}.MathJax_MenuCheck{position:absolute;left:.7em}.MathJax_MenuCheck.RTL{right:.7em;left:auto}.MathJax_MenuRadioCheck{position:absolute;left:1em}.MathJax_MenuRadioCheck.RTL{right:1em;left:auto}.MathJax_MenuLabel{padding:2px 2em 4px 1.33em;font-style:italic}.MathJax_MenuRule{border-top:1px solid #CCC;margin:4px 1px 0}.MathJax_MenuDisabled{color:GrayText}.MathJax_MenuActive{background-color:Highlight;color:HighlightText}.MathJax_Menu_Close{position:absolute;width:31px;height:31px;top:-15px;left:-15px}#MathJax_Zoom{position:absolute;background-color:#F0F0F0;overflow:auto;display:block;z-index:301;padding:.5em;border:1px solid #000;margin:0;font-weight:400;font-style:normal;text-align:left;text-indent:0;text-transform:none;line-height:normal;letter-spacing:normal;word-spacing:normal;word-wrap:normal;white-space:nowrap;float:none;box-shadow:5px 5px 15px #AAA;-webkit-box-shadow:5px 5px 15px #AAA;-moz-box-shadow:5px 5px 15px #AAA;-khtml-box-shadow:5px 5px 15px #AAA;filter:progid:DXImageTransform.Microsoft.dropshadow(OffX=2, OffY=2, Color='gray', Positive='true')}#MathJax_ZoomOverlay{position:absolute;left:0;top:0;z-index:300;display:inline-block;width:100%;height:100%;border:0;padding:0;margin:0;background-color:#fff;opacity:0;filter:alpha(opacity=0)}#MathJax_ZoomFrame{position:relative;display:inline-block;height:0;width:0}#MathJax_ZoomEventTrap{position:absolute;left:0;top:0;z-index:302;display:inline-block;border:0;padding:0;margin:0;background-color:#fff;opacity:0;filter:alpha(opacity=0)}.MathJax_Preview{color:#888}#MathJax_Message{position:fixed;left:1px;bottom:2px;background-color:#E6E6E6;border:1px solid #959595;margin:0;padding:2px 8px;z-index:102;color:#000;font-size:80%;width:auto;white-space:nowrap}#MathJax_MSIE_Frame{position:absolute;top:0;left:0;width:0;z-index:101;border:0;margin:0;padding:0}.MathJax_Error{color:#C00;font-style:italic}footer{position:fixed;font-size:.8em;text-align:right;bottom:0;margin-left:-25px;height:20px;width:100%}</style>
</head>
<body class="markdown haroopad">
<h2 id="changes"><a name="changes" href="#changes"></a>Changes</h2><h2 id="update:-1.10.0"><a name="update:-1.10.0" href="#update:-1.10.0"></a>Update: 1.10.0</h2><p><strong>Note:</strong> The library is now considered to be stable!<br><strong>Upcoming:</strong> Network parallelism is on the way. It is in the works and should be released soon</p><h2 id="added:"><a name="added:" href="#added:"></a>Added:</h2><ul>
<li>isMainThread true/nil</li><li>multi:newSystemThreadedConnection(name,protect) — Works like normal connections, but are able to trigger events across threads</li></ul><p>Example of threaded connections</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>package.path=&quot;?/init.lua;?.lua;&quot;..package.path
local GLOBAL,THREAD=require(&quot;multi.integration.lanesManager&quot;).init()
multi:newSystemThread(&quot;Test_Thread_1&quot;,function()
connOut = THREAD.waitFor(&quot;ConnectionNAMEHERE&quot;):init()
connOut(function(arg)
print(THREAD.getName(),arg)
end)
multi:mainloop()
end)
multi:newSystemThread(&quot;Test_Thread_2&quot;,function()
connOut = THREAD.waitFor(&quot;ConnectionNAMEHERE&quot;):init()
connOut(function(arg)
print(THREAD.getName(),arg)
end)
multi:mainloop()
end)
connOut = multi:newSystemThreadedConnection(&quot;ConnectionNAMEHERE&quot;):init()
a=0
connOut(function(arg)
print(&quot;Main&quot;,arg)
end)
multi:newTLoop(function()
a=a+1
connOut:Fire(&quot;Test From Main Thread: &quot;..a..&quot;\n&quot;)
end,1)
</code></pre>"><span class="hljs-built_in">package</span>.path=<span class="hljs-string">"?/init.lua;?.lua;"</span>..<span class="hljs-built_in">package</span>.path
<span class="hljs-keyword">local</span> GLOBAL,THREAD=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.lanesManager"</span>).init()
multi:newSystemThread(<span class="hljs-string">"Test_Thread_1"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
connOut = THREAD.waitFor(<span class="hljs-string">"ConnectionNAMEHERE"</span>):init()
connOut(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(arg)</span></span>
<span class="hljs-built_in">print</span>(THREAD.getName(),arg)
<span class="hljs-keyword">end</span>)
multi:mainloop()
<span class="hljs-keyword">end</span>)
multi:newSystemThread(<span class="hljs-string">"Test_Thread_2"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
connOut = THREAD.waitFor(<span class="hljs-string">"ConnectionNAMEHERE"</span>):init()
connOut(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(arg)</span></span>
<span class="hljs-built_in">print</span>(THREAD.getName(),arg)
<span class="hljs-keyword">end</span>)
multi:mainloop()
<span class="hljs-keyword">end</span>)
connOut = multi:newSystemThreadedConnection(<span class="hljs-string">"ConnectionNAMEHERE"</span>):init()
a=<span class="hljs-number">0</span>
connOut(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(arg)</span></span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Main"</span>,arg)
<span class="hljs-keyword">end</span>)
multi:newTLoop(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
a=a+<span class="hljs-number">1</span>
connOut:Fire(<span class="hljs-string">"Test From Main Thread: "</span>..a..<span class="hljs-string">"\n"</span>)
<span class="hljs-keyword">end</span>,<span class="hljs-number">1</span>)
</code></pre><h2 id="fixed:"><a name="fixed:" href="#fixed:"></a>Fixed:</h2><p><strong>loveManager</strong> and <strong>shared threading objects</strong></p><ul>
<li>sThread.waitFor()</li><li>sThread.hold()</li><li>some typos</li><li>SystemThreadedTables (They now work on both lanes and love2d as expected)</li></ul><p>Example of threaded tables</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>package.path=&quot;?/init.lua;?.lua;&quot;..package.path
local GLOBAL,sThread=require(&quot;multi.integration.lanesManager&quot;).init()
multi:newSystemThread(&quot;Test_Thread_1&quot;,function()
require(&quot;multi&quot;)
test = sThread.waitFor(&quot;testthing&quot;):init()
multi:newTLoop(function()
print(&quot;------&quot;)
for i,v in pairs(test.tab) do
print(&quot;T1&quot;,i,v)
end
end,1)
multi:mainloop()
end)
multi:newSystemThread(&quot;Test_Thread_1&quot;,function()
require(&quot;multi&quot;)
test = sThread.waitFor(&quot;testthing&quot;):init()
multi:newTLoop(function()
print(&quot;------&quot;)
for i,v in pairs(test.tab) do
print(&quot;T2&quot;,i,v)
end
end,1)
multi:mainloop()
end)
test = multi:newSystemThreadedTable(&quot;testthing&quot;):init()
multi:newTLoop(function()
local a,b = multi.randomString(8),multi.randomString(4)
print(&quot;&amp;gt;&quot;,a,b)
test[a]=b
end,1)
multi:mainloop()
</code></pre>"><span class="hljs-built_in">package</span>.path=<span class="hljs-string">"?/init.lua;?.lua;"</span>..<span class="hljs-built_in">package</span>.path
<span class="hljs-keyword">local</span> GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.lanesManager"</span>).init()
multi:newSystemThread(<span class="hljs-string">"Test_Thread_1"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi"</span>)
test = sThread.waitFor(<span class="hljs-string">"testthing"</span>):init()
multi:newTLoop(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"------"</span>)
<span class="hljs-keyword">for</span> i,v <span class="hljs-keyword">in</span> <span class="hljs-built_in">pairs</span>(test.tab) <span class="hljs-keyword">do</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"T1"</span>,i,v)
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>,<span class="hljs-number">1</span>)
multi:mainloop()
<span class="hljs-keyword">end</span>)
multi:newSystemThread(<span class="hljs-string">"Test_Thread_1"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi"</span>)
test = sThread.waitFor(<span class="hljs-string">"testthing"</span>):init()
multi:newTLoop(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"------"</span>)
<span class="hljs-keyword">for</span> i,v <span class="hljs-keyword">in</span> <span class="hljs-built_in">pairs</span>(test.tab) <span class="hljs-keyword">do</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"T2"</span>,i,v)
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>,<span class="hljs-number">1</span>)
multi:mainloop()
<span class="hljs-keyword">end</span>)
test = multi:newSystemThreadedTable(<span class="hljs-string">"testthing"</span>):init()
multi:newTLoop(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-keyword">local</span> a,b = multi.randomString(<span class="hljs-number">8</span>),multi.randomString(<span class="hljs-number">4</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">"&gt;"</span>,a,b)
test[a]=b
<span class="hljs-keyword">end</span>,<span class="hljs-number">1</span>)
multi:mainloop()
</code></pre><h2 id="update:-1.9.2"><a name="update:-1.9.2" href="#update:-1.9.2"></a>Update: 1.9.2</h2><p>Added:</p><ul>
<li>(THREAD).kill() kills a thread. Note: THREAD is based on what you name it</li><li>newTimeStamper() Part of the persistant systems… Useful for when you are running this library for a massive amount of time… like years stright!<br>Allows one to hook to timed events such as whenever the clock strikes midnight or when the day turns to monday. The event is only done once though. so as soon as monday is set it would trigger then not trigger again until next monday<br>works for seconds, minutes, days, months, year.<pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>stamper = multi:newTimeStamper()
stamper:OnTime(int hour,int minute,int second,func) or stamper:OnTime(string time,func) time as 00:00:00
stamper:OnHour(int hour,func)
stamper:OnMinute(int minute,func)
stamper:OnSecond(int second,func)
stamper:OnDay(int day,func) or stamper:OnDay(string day,func) Mon, Tues, Wed, etc...
stamper:OnMonth(int month,func)
stamper:OnYear(int year,func)
</code></pre>">stamper = multi:newTimeStamper()
stamper:OnTime(int hour,int minute,int second,func) <span class="hljs-keyword">or</span> stamper:OnTime(<span class="hljs-built_in">string</span> time,func) time as <span class="hljs-number">00</span>:<span class="hljs-number">00</span>:<span class="hljs-number">00</span>
stamper:OnHour(int hour,func)
stamper:OnMinute(int minute,func)
stamper:OnSecond(int second,func)
stamper:OnDay(int day,func) <span class="hljs-keyword">or</span> stamper:OnDay(<span class="hljs-built_in">string</span> day,func) Mon, Tues, Wed, etc...
stamper:OnMonth(int month,func)
stamper:OnYear(int year,func)
</code></pre>
Updated:</li><li>LoadBalancing, well bettwr load balancing than existed before. This one allowd for multiple processes to have their own load reading. Calling this on the multi object will return the total load for the entire multi enviroment… loads of other processes are indeed affected by what other processes are doing. However if you combine prorioty to the mix of things then you will get differing results… these results however will most likely be higher than normal… different pirorities will have different default thresholds of performence.</li></ul><p>Fixed:</p><ul>
<li>Thread.getName() should now work on lanes and love2d, havent tested ut nuch with the luvit side of things…</li><li>A bug with the lovemanager table.remove arguments were backwards haha</li><li>The queue object in the love2d threading has been fixed! It now supports sending all objects (even functions as long as no upvalues are present!)</li></ul><p>Changed:</p><ul>
<li>SystemThreadedJobQueues now have built in load management so they are not constantly at 100% cpu usage.</li><li>SystemThreadedJobQueues pushJob now retunts an id of that job which will match the same one that OnJobCompleted returns</li></ul><h2 id="update:-1.9.1"><a name="update:-1.9.1" href="#update:-1.9.1"></a>Update: 1.9.1</h2><p>Added:</p><ul>
<li>Integration “multi.integration.luvitManager”</li><li>Limited… Only the basic multi:newSystemThread(…) will work</li><li>Not even data passing will work other than arguments… If using the bin library you can pass tables and function… Even full objects as long as inner recursion is not preasent.</li></ul><p>Updated:</p><ul>
<li>multi:newSystemThread(name,func,…)</li><li>It will not pass the … to the func(). Do not know why this wasnt done in the first place :P</li><li>Also multi:getPlatform(will now return “luvit” if using luvit… Though Idk if module creators would use the multi library when inside the luvit enviroment</li></ul><h2 id="update:-1.9.0"><a name="update:-1.9.0" href="#update:-1.9.0"></a>Update: 1.9.0</h2><p>Added:</p><ul>
<li>multiobj:ToString() — returns a string repersenting the object</li><li>multi:newFromString(str) — creates an object from a string</li></ul><p>Works on threads and regular objects. Requires the latest bin library to work!</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>talarm=multi:newThreadedAlarm(&quot;AlarmTest&quot;,5)
talarm:OnRing(function()
print(&quot;Ring!&quot;)
end)
bin.new(talarm:ToString()):tofile(&quot;test.dat&quot;)
-- multi:newFromString(bin.load(&quot;test.dat&quot;))
</code></pre>">talarm=multi:newThreadedAlarm(<span class="hljs-string">"AlarmTest"</span>,<span class="hljs-number">5</span>)
talarm:OnRing(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Ring!"</span>)
<span class="hljs-keyword">end</span>)
bin.new(talarm:ToString()):tofile(<span class="hljs-string">"test.dat"</span>)
<span class="hljs-comment">-- multi:newFromString(bin.load("test.dat"))</span>
</code></pre><p>— A more seamless way to use this will be made in the form of state saving.<br>This is still a WIP<br>processes, timers, timemasters, watchers, and queuers have not been worked on yet</p><h2 id="update:-1.8.7"><a name="update:-1.8.7" href="#update:-1.8.7"></a>Update: 1.8.7</h2><p>Added:</p><ul>
<li>multi.timer(func,…)</li></ul><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>function test(a,b,c)
print(&quot;Running...&quot;)
a=0
for i=1,1000000000 do
a=a+1
end
return a,b+c
end
print(multi.timer(test,1,2,3))
print(multi.timer(test,1,2,3))
-- multi.timer returns the time taken then the arguments from the function... Uses unpack so careful of nil values!
</code></pre>"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">test</span><span class="hljs-params">(a,b,c)</span></span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Running..."</span>)
a=<span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> i=<span class="hljs-number">1</span>,<span class="hljs-number">1000000000</span> <span class="hljs-keyword">do</span>
a=a+<span class="hljs-number">1</span>
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">return</span> a,b+c
<span class="hljs-keyword">end</span>
<span class="hljs-built_in">print</span>(multi.timer(test,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>))
<span class="hljs-built_in">print</span>(multi.timer(test,<span class="hljs-number">1</span>,<span class="hljs-number">2</span>,<span class="hljs-number">3</span>))
<span class="hljs-comment">-- multi.timer returns the time taken then the arguments from the function... Uses unpack so careful of nil values!</span>
</code></pre><h2 id="update:-1.8.6"><a name="update:-1.8.6" href="#update:-1.8.6"></a>Update: 1.8.6</h2><p>Added:</p><ul>
<li>jobQueue:doToAll(function)</li><li>jobQueue:start() is now required Call this after all calls to registerJob()s. Calling it afterwards will not guarantee your next push job with that job will work. Not calling this will make pushing jobs impossible!</li><li>Fixed a bug with love2d Threaded Queue</li><li>Fixed some bugs</li><li>Old versions of this library! It stems back from 2012 see rambling for more info…</li></ul><p>This will run said function in every thread.</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- Going to use love2d code this time, almost the same as last time... See ramblings
require(&quot;core.Library&quot;)
GLOBAL,sThread=require(&quot;multi.integration.loveManager&quot;).init() -- load the love2d version of the lanesManager and requires the entire multi library
require(&quot;core.GuiManager&quot;)
gui.ff.Color=Color.Black
jQueue=multi:newSystemThreadedJobQueue()
jQueue:registerJob(&quot;TEST_JOB&quot;,function(a,s)
math.randomseed(s)
TEST_JOB2()
return math.random(0,255)
end)
jQueue:registerJob(&quot;TEST_JOB2&quot;,function()
print(&quot;Test Works!&quot;)
end)
-- 1.8.6 EXAMPLE Change
jQueue:start() -- This is now needed!
--
jQueue:doToAll(function()
print(&quot;Doing this 2? times!&quot;)
end)
tableOfOrder={}
jQueue.OnJobCompleted(function(JOBID,n)
tableOfOrder[JOBID]=n
if #tableOfOrder==10 then
t.text=&quot;We got all of the pieces!&quot;
end
end)
for i=1,10 do -- Job Name of registered function, ... varargs
jQueue:pushJob(&quot;TEST_JOB&quot;,&quot;This is a test!&quot;,math.random(1,1000000))
end
t=gui:newTextLabel(&quot;no done yet!&quot;,0,0,300,100)
t:centerX()
t:centerY()
</code></pre>"><span class="hljs-comment">-- Going to use love2d code this time, almost the same as last time... See ramblings</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"core.Library"</span>)
GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.loveManager"</span>).init() <span class="hljs-comment">-- load the love2d version of the lanesManager and requires the entire multi library</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"core.GuiManager"</span>)
gui.ff.Color=Color.Black
jQueue=multi:newSystemThreadedJobQueue()
jQueue:registerJob(<span class="hljs-string">"TEST_JOB"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(a,s)</span></span>
<span class="hljs-built_in">math</span>.randomseed(s)
TEST_JOB2()
<span class="hljs-keyword">return</span> <span class="hljs-built_in">math</span>.random(<span class="hljs-number">0</span>,<span class="hljs-number">255</span>)
<span class="hljs-keyword">end</span>)
jQueue:registerJob(<span class="hljs-string">"TEST_JOB2"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Test Works!"</span>)
<span class="hljs-keyword">end</span>)
<span class="hljs-comment">-- 1.8.6 EXAMPLE Change</span>
jQueue:start() <span class="hljs-comment">-- This is now needed!</span>
<span class="hljs-comment">--</span>
jQueue:doToAll(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Doing this 2? times!"</span>)
<span class="hljs-keyword">end</span>)
tableOfOrder={}
jQueue.OnJobCompleted(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(JOBID,n)</span></span>
tableOfOrder[JOBID]=n
<span class="hljs-keyword">if</span> #tableOfOrder==<span class="hljs-number">10</span> <span class="hljs-keyword">then</span>
t.text=<span class="hljs-string">"We got all of the pieces!"</span>
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>)
<span class="hljs-keyword">for</span> i=<span class="hljs-number">1</span>,<span class="hljs-number">10</span> <span class="hljs-keyword">do</span> <span class="hljs-comment">-- Job Name of registered function, ... varargs</span>
jQueue:pushJob(<span class="hljs-string">"TEST_JOB"</span>,<span class="hljs-string">"This is a test!"</span>,<span class="hljs-built_in">math</span>.random(<span class="hljs-number">1</span>,<span class="hljs-number">1000000</span>))
<span class="hljs-keyword">end</span>
t=gui:newTextLabel(<span class="hljs-string">"no done yet!"</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">300</span>,<span class="hljs-number">100</span>)
t:centerX()
t:centerY()
</code></pre><h2 id="update:-1.8.5"><a name="update:-1.8.5" href="#update:-1.8.5"></a>Update: 1.8.5</h2><p>Added:</p><ul>
<li>SystemThreadedExecute(cmd)</li></ul><p>Allows the execution of system calls without hold up. It is possible to do the same using io.popen()! You decide which works best for you!</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>local GLOBAL,sThread=require(&quot;multi.integration.lanesManager&quot;).init()
cmd=multi:newSystemThreadedExecute(&quot;SystemThreadedExecuteTest.lua&quot;) -- This file is important!
cmd.OnCMDFinished(function(code) -- callback function to grab the exit code... Called when the command goes through
print(&quot;Got Code: &quot;..code)
end)
multi:newTLoop(function()
print(&quot;...&quot;) -- lets show that we aren't being held up
end,1)
multi:mainloop()
</code></pre>"><span class="hljs-keyword">local</span> GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.lanesManager"</span>).init()
cmd=multi:newSystemThreadedExecute(<span class="hljs-string">"SystemThreadedExecuteTest.lua"</span>) <span class="hljs-comment">-- This file is important!</span>
cmd.OnCMDFinished(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(code)</span></span> <span class="hljs-comment">-- callback function to grab the exit code... Called when the command goes through</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Got Code: "</span>..code)
<span class="hljs-keyword">end</span>)
multi:newTLoop(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"..."</span>) <span class="hljs-comment">-- lets show that we aren't being held up</span>
<span class="hljs-keyword">end</span>,<span class="hljs-number">1</span>)
multi:mainloop()
</code></pre><h2 id="update:-1.8.4"><a name="update:-1.8.4" href="#update:-1.8.4"></a>Update: 1.8.4</h2><p>Added:</p><ul>
<li>multi:newSystemThreadedJobQueue()</li><li>Improved stability of the library</li><li>Fixed a bug that made the benchmark and getload commands non-thread(coroutine) safe</li><li>Tweaked the loveManager to help improve idle cpu usage</li><li>Minor tweaks to the coroutine scheduling</li></ul><h1 id="using-multi:newsystemthreadedjobqueue()"><a name="using-multi:newsystemthreadedjobqueue()" href="#using-multi:newsystemthreadedjobqueue()"></a>Using multi:newSystemThreadedJobQueue()</h1><p>First you need to create the object<br>This works the same way as love2d as it does with lanes… It is getting increasing harder to make both work the same way with speed in mind… Anyway…</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- Creating the object using lanes manager to show case this. Examples has the file for love2d
local GLOBAL,sThread=require(&quot;multi.integration.lanesManager&quot;).init()
jQueue=multi:newSystemThreadedJobQueue(n) -- this internally creates System threads. By defualt it will use the # of processors on your system You can set this number though.
-- Only create 1 jobqueue! For now making more than 1 is buggy. You only really need one though. Just register new functions if you want 1 queue to do more. The one reason though is keeping track of jobIDs. I have an idea that I will roll out in the next update.
jQueue:registerJob(&quot;TEST_JOB&quot;,function(a,s)
math.randomseed(s)
-- We will push a random #
TEST_JOB2() -- You can call other registered functions as well!
return math.random(0,255) -- send the result to the main thread
end)
jQueue:registerJob(&quot;TEST_JOB2&quot;,function()
print(&quot;Test Works!&quot;) -- this is called from the job since it is registered on the same queue
end)
tableOfOrder={} -- This is how we will keep order of our completed jobs. There is no guarantee that the order will be correct
jQueue.OnJobCompleted(function(JOBID,n) -- whenever a job is completed you hook to the event that is called. This passes the JOBID folled by the returns of the job
-- JOBID is the completed job, starts at 1 and counts up by 1.
-- Threads finish at different times so jobids may be passed out of order! Be sure to have a way to order them
tableOfOrder[JOBID]=n -- we order ours by putting them into a table
if #tableOfOrder==10 then
print(&quot;We got all of the pieces!&quot;)
end
end)
-- Lets push the jobs now
for i=1,10 do -- Job Name of registered function, ... varargs
jQueue:pushJob(&quot;TEST_JOB&quot;,&quot;This is a test!&quot;,math.random(1,1000000))
end
print(&quot;I pushed all of the jobs :)&quot;)
multi:mainloop() -- Start the main loop :D
</code></pre>"><span class="hljs-comment">-- Creating the object using lanes manager to show case this. Examples has the file for love2d</span>
<span class="hljs-keyword">local</span> GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.lanesManager"</span>).init()
jQueue=multi:newSystemThreadedJobQueue(n) <span class="hljs-comment">-- this internally creates System threads. By defualt it will use the # of processors on your system You can set this number though.</span>
<span class="hljs-comment">-- Only create 1 jobqueue! For now making more than 1 is buggy. You only really need one though. Just register new functions if you want 1 queue to do more. The one reason though is keeping track of jobIDs. I have an idea that I will roll out in the next update.</span>
jQueue:registerJob(<span class="hljs-string">"TEST_JOB"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(a,s)</span></span>
<span class="hljs-built_in">math</span>.randomseed(s)
<span class="hljs-comment">-- We will push a random #</span>
TEST_JOB2() <span class="hljs-comment">-- You can call other registered functions as well!</span>
<span class="hljs-keyword">return</span> <span class="hljs-built_in">math</span>.random(<span class="hljs-number">0</span>,<span class="hljs-number">255</span>) <span class="hljs-comment">-- send the result to the main thread</span>
<span class="hljs-keyword">end</span>)
jQueue:registerJob(<span class="hljs-string">"TEST_JOB2"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Test Works!"</span>) <span class="hljs-comment">-- this is called from the job since it is registered on the same queue</span>
<span class="hljs-keyword">end</span>)
tableOfOrder={} <span class="hljs-comment">-- This is how we will keep order of our completed jobs. There is no guarantee that the order will be correct</span>
jQueue.OnJobCompleted(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(JOBID,n)</span></span> <span class="hljs-comment">-- whenever a job is completed you hook to the event that is called. This passes the JOBID folled by the returns of the job</span>
<span class="hljs-comment">-- JOBID is the completed job, starts at 1 and counts up by 1.</span>
<span class="hljs-comment">-- Threads finish at different times so jobids may be passed out of order! Be sure to have a way to order them</span>
tableOfOrder[JOBID]=n <span class="hljs-comment">-- we order ours by putting them into a table</span>
<span class="hljs-keyword">if</span> #tableOfOrder==<span class="hljs-number">10</span> <span class="hljs-keyword">then</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"We got all of the pieces!"</span>)
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>)
<span class="hljs-comment">-- Lets push the jobs now</span>
<span class="hljs-keyword">for</span> i=<span class="hljs-number">1</span>,<span class="hljs-number">10</span> <span class="hljs-keyword">do</span> <span class="hljs-comment">-- Job Name of registered function, ... varargs</span>
jQueue:pushJob(<span class="hljs-string">"TEST_JOB"</span>,<span class="hljs-string">"This is a test!"</span>,<span class="hljs-built_in">math</span>.random(<span class="hljs-number">1</span>,<span class="hljs-number">1000000</span>))
<span class="hljs-keyword">end</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"I pushed all of the jobs :)"</span>)
multi:mainloop() <span class="hljs-comment">-- Start the main loop :D</span>
</code></pre><p>Thats it from this version!</p><h2 id="update:-1.8.3"><a name="update:-1.8.3" href="#update:-1.8.3"></a>Update: 1.8.3</h2><p>Added:<br><br><strong>New Mainloop functions</strong> Below you can see the slight differences… Function overhead is not too bad in lua, but has a real difference. multi:mainloop() and multi:unprotectedMainloop() use the same algorithm yet the dedicated unprotected one is slightly faster due to having less function overhead.</p><ul>
<li>multi:mainloop()* — Bench: 16830003 Steps in 3 second(s)!</li><li>multi:protectedMainloop() — Bench: 16699308 Steps in 3 second(s)!</li><li>multi:unprotectedMainloop() — Bench: 16976627 Steps in 3 second(s)!</li><li>multi:prioritizedMainloop1() — Bench: 15007133 Steps in 3 second(s)!</li><li>multi:prioritizedMainloop2() — Bench: 15526248 Steps in 3 second(s)!</li></ul><p>* The OG mainloop function remains the same and old methods to achieve what we have with the new ones still exist</p><p>These new methods help by removing function overhead that is caused through the original mainloop function. The one downside is that you no longer have the flexiblity to change the processing during runtime.</p><p>However there is a work around! You can use processes to run multiobjs as well and use the other methods on them.</p><p>I may make a full comparison between each method and which is faster, but for now trust that the dedicated ones with less function overhead are infact faster. Not by much but still faster. :D</p><h2 id="update:-1.8.2"><a name="update:-1.8.2" href="#update:-1.8.2"></a>Update: 1.8.2</h2><p>Added:<br></p><ul>
<li>multi:newsystemThreadedTable(name) NOTE: Metatables are not supported in transfers. However there is a work around obj:init() that you see does this. Take a look in the multi/integration/shared/shared.lua files to see how I did it!</li><li>Modified the GLOBAL metatable to sync before doing its tests</li><li>multi._VERSION was multi.Version, felt it would be more consistant this way… I left the old way of getting the version just incase someone has used that way. It will eventually be gone. Also multi:getVersion() will do the job just as well and keep your code nice and update related bug free!</li><li>Also everything that is included in the: multi/integration/shared/shared.lua (Which is loaded automatically) works in both lanes and love2d enviroments!</li></ul><p>The threaded table is setup just like the threaded queue.<br><br>It provids GLOBAL like features without having to write to GLOBAL!<br><br>This is useful for module creators who want to keep their data private, but also use GLOBAL like coding.<br><br>It has a few features that makes it a bit better than plain ol GLOBAL (For now…)<br>(ThreadedTable - TT for short)</p><ul>
<li>TT:waitFor(name)</li><li>TT:sync()</li><li>TT[“var”]=value</li><li>print(TT[“var”])</li></ul><p>we also have the “sync” method, this one was made for love2d because we do a syncing trick to get data in a table format. The lanes side has a sync method as well so no worries. Using indexing calls sync once and may grab your variable. This allows you to have the lanes indexing like syntax when doing regular indexing in love2d side of the module. As of right now both sides work flawlessly! And this effect is now the GLOBAL as well<br></p><p>On GLOBALS sync is a internal method for keeping the GLOBAL table in order. You can still use sThread.waitFor(name) to wait for variables that may of may not yet exist!</p><p>Time for some examples:</p><h1 id="using-multi:newsystemthreadedtable(name)"><a name="using-multi:newsystemthreadedtable(name)" href="#using-multi:newsystemthreadedtable(name)"></a>Using multi:newSystemThreadedTable(name)</h1><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- lanes Desktop lua! NOTE: this is in lanesintergratetest6.lua in the examples folder
local GLOBAL,sThread=require(&quot;multi.integration.lanesManager&quot;).init()
test=multi:newSystemThreadedTable(&quot;YO&quot;):init()
test[&quot;test1&quot;]=&quot;lol&quot;
multi:newSystemThread(&quot;test&quot;,function()
tab=sThread.waitFor(&quot;YO&quot;):init()
print(tab:has(&quot;test1&quot;))
sThread.sleep(3)
tab[&quot;test2&quot;]=&quot;Whats so funny?&quot;
end)
multi:newThread(&quot;test2&quot;,function()
print(test:waitFor(&quot;test2&quot;))
end)
multi:mainloop()
</code></pre>"><span class="hljs-comment">-- lanes Desktop lua! NOTE: this is in lanesintergratetest6.lua in the examples folder</span>
<span class="hljs-keyword">local</span> GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.lanesManager"</span>).init()
test=multi:newSystemThreadedTable(<span class="hljs-string">"YO"</span>):init()
test[<span class="hljs-string">"test1"</span>]=<span class="hljs-string">"lol"</span>
multi:newSystemThread(<span class="hljs-string">"test"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
tab=sThread.waitFor(<span class="hljs-string">"YO"</span>):init()
<span class="hljs-built_in">print</span>(tab:has(<span class="hljs-string">"test1"</span>))
sThread.sleep(<span class="hljs-number">3</span>)
tab[<span class="hljs-string">"test2"</span>]=<span class="hljs-string">"Whats so funny?"</span>
<span class="hljs-keyword">end</span>)
multi:newThread(<span class="hljs-string">"test2"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">print</span>(test:waitFor(<span class="hljs-string">"test2"</span>))
<span class="hljs-keyword">end</span>)
multi:mainloop()
</code></pre><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- love2d gaming lua! NOTE: this is in main4.lua in the love2d examples
require(&quot;core.Library&quot;)
GLOBAL,sThread=require(&quot;multi.integration.loveManager&quot;).init() -- load the love2d version of the lanesManager and requires the entire multi library
require(&quot;core.GuiManager&quot;)
gui.ff.Color=Color.Black
test=multi:newSystemThreadedTable(&quot;YO&quot;):init()
test[&quot;test1&quot;]=&quot;lol&quot;
multi:newSystemThread(&quot;test&quot;,function()
tab=sThread.waitFor(&quot;YO&quot;):init()
print(tab[&quot;test1&quot;])
sThread.sleep(3)
tab[&quot;test2&quot;]=&quot;Whats so funny?&quot;
end)
multi:newThread(&quot;test2&quot;,function()
print(test:waitFor(&quot;test2&quot;))
t.text=&quot;DONE!&quot;
end)
t=gui:newTextLabel(&quot;no done yet!&quot;,0,0,300,100)
t:centerX()
t:centerY()
</code></pre>"><span class="hljs-comment">-- love2d gaming lua! NOTE: this is in main4.lua in the love2d examples</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"core.Library"</span>)
GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.loveManager"</span>).init() <span class="hljs-comment">-- load the love2d version of the lanesManager and requires the entire multi library</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"core.GuiManager"</span>)
gui.ff.Color=Color.Black
test=multi:newSystemThreadedTable(<span class="hljs-string">"YO"</span>):init()
test[<span class="hljs-string">"test1"</span>]=<span class="hljs-string">"lol"</span>
multi:newSystemThread(<span class="hljs-string">"test"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
tab=sThread.waitFor(<span class="hljs-string">"YO"</span>):init()
<span class="hljs-built_in">print</span>(tab[<span class="hljs-string">"test1"</span>])
sThread.sleep(<span class="hljs-number">3</span>)
tab[<span class="hljs-string">"test2"</span>]=<span class="hljs-string">"Whats so funny?"</span>
<span class="hljs-keyword">end</span>)
multi:newThread(<span class="hljs-string">"test2"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-built_in">print</span>(test:waitFor(<span class="hljs-string">"test2"</span>))
t.text=<span class="hljs-string">"DONE!"</span>
<span class="hljs-keyword">end</span>)
t=gui:newTextLabel(<span class="hljs-string">"no done yet!"</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">300</span>,<span class="hljs-number">100</span>)
t:centerX()
t:centerY()
</code></pre><h2 id="update:-1.8.1"><a name="update:-1.8.1" href="#update:-1.8.1"></a>Update: 1.8.1</h2><p>No real change!<br><br>Changed the structure of the library. Combined the coroutine based threads into the core!<br><br>Only compat and integrations are not part of the core and never will be by nature.<br><br>This should make the library more convient to use.<br><br>I left multi/all.lua file so if anyone had libraries/projects that used that it will still work!<br><br>Updated from 1.7.6 to 1.8.0<br> (How much thread could a thread thread if a thread could thread thread?)<br>Added:<br></p><ul>
<li>multi:newSystemThreadedQueue()</li><li>multi:systemThreadedBenchmark()</li><li>More example files</li><li>multi:canSystemThread() — true if an integration was added false otherwise (For module creation)</li><li>Fixed a few bugs in the loveManager</li></ul><h1 id="using-multi:systemthreadedbenchmark()"><a name="using-multi:systemthreadedbenchmark()" href="#using-multi:systemthreadedbenchmark()"></a>Using multi:systemThreadedBenchmark()</h1><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>package.path=&quot;?/init.lua;&quot;..package.path
local GLOBAL,sThread=require(&quot;multi.integration.lanesManager&quot;).init()
multi:systemThreadedBenchmark(3):OnBench(function(self,count)
print(&quot;First Bench: &quot;..count)
multi:systemThreadedBenchmark(3,&quot;All Threads: &quot;)
end)
multi:mainloop()
</code></pre>"><span class="hljs-built_in">package</span>.path=<span class="hljs-string">"?/init.lua;"</span>..<span class="hljs-built_in">package</span>.path
<span class="hljs-keyword">local</span> GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.lanesManager"</span>).init()
multi:systemThreadedBenchmark(<span class="hljs-number">3</span>):OnBench(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self,count)</span></span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"First Bench: "</span>..count)
multi:systemThreadedBenchmark(<span class="hljs-number">3</span>,<span class="hljs-string">"All Threads: "</span>)
<span class="hljs-keyword">end</span>)
multi:mainloop()
</code></pre><h1 id="using-multi:newsystemthreadedqueue()"><a name="using-multi:newsystemthreadedqueue()" href="#using-multi:newsystemthreadedqueue()"></a>Using multi:newSystemThreadedQueue()</h1><p>Quick Note: queues shared across multiple objects will be pulling from the same “queue” keep this in mind when coding! <del>Also the queue respects direction a push on the thread side cannot be popped on the thread side… Same goes for the mainthread!<br></del> Turns out i was wrong about this…</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- in love2d, this file will be in the same example folder as before, but is named main2.lua
require(&quot;core.Library&quot;)
GLOBAL,sThread=require(&quot;multi.integration.loveManager&quot;).init() -- load the love2d version of the lanesManager and requires the entire multi library
--IMPORTANT
-- Do not make the above local, this is the one difference that the lanesManager does not have
-- If these are local the functions will have the upvalues put into them that do not exist on the threaded side
-- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though
-- Also each thread has a .1 second delay! This is used to generate a random values for each thread!
require(&quot;core.GuiManager&quot;)
gui.ff.Color=Color.Black
function multi:newSystemThreadedQueue(name) -- in love2d this will spawn a channel on both ends
local c={}
c.name=name
if love then
if love.thread then
function c:init()
self.chan=love.thread.getChannel(self.name)
function self:push(v)
self.chan:push(v)
end
function self:pop()
return self.chan:pop()
end
GLOBAL[self.name]=self
return self
end
return c
else
error(&quot;Make sure you required the love.thread module!&quot;)
end
else
c.linda=lanes.linda()
function c:push(v)
self.linda:send(&quot;Q&quot;,v)
end
function c:pop()
return ({self.linda:receive(0,&quot;Q&quot;)})[2]
end
function c:init()
return self
end
GLOBAL[name]=c
end
return c
end
queue=multi:newSystemThreadedQueue(&quot;QUEUE&quot;):init()
queue:push(&quot;This is a test&quot;)
queue:push(&quot;This is a test2&quot;)
queue:push(&quot;This is a test3&quot;)
queue:push(&quot;This is a test4&quot;)
multi:newSystemThread(&quot;test2&quot;,function()
queue=sThread.waitFor(&quot;QUEUE&quot;):init()
data=queue:pop()
while data do
print(data)
data=queue:pop()
end
queue:push(&quot;DONE!&quot;)
end)
multi:newThread(&quot;test!&quot;,function()
thread.hold(function() return queue:pop() end)
t.text=&quot;Done!&quot;
end)
t=gui:newTextLabel(&quot;no done yet!&quot;,0,0,300,100)
t:centerX()
t:centerY()
</code></pre>"><span class="hljs-comment">-- in love2d, this file will be in the same example folder as before, but is named main2.lua</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"core.Library"</span>)
GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.loveManager"</span>).init() <span class="hljs-comment">-- load the love2d version of the lanesManager and requires the entire multi library</span>
<span class="hljs-comment">--IMPORTANT</span>
<span class="hljs-comment">-- Do not make the above local, this is the one difference that the lanesManager does not have</span>
<span class="hljs-comment">-- If these are local the functions will have the upvalues put into them that do not exist on the threaded side</span>
<span class="hljs-comment">-- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though</span>
<span class="hljs-comment">-- Also each thread has a .1 second delay! This is used to generate a random values for each thread!</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"core.GuiManager"</span>)
gui.ff.Color=Color.Black
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">multi:newSystemThreadedQueue</span><span class="hljs-params">(name)</span></span> <span class="hljs-comment">-- in love2d this will spawn a channel on both ends</span>
<span class="hljs-keyword">local</span> c={}
c.name=name
<span class="hljs-keyword">if</span> love <span class="hljs-keyword">then</span>
<span class="hljs-keyword">if</span> love.thread <span class="hljs-keyword">then</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">c:init</span><span class="hljs-params">()</span></span>
self.chan=love.thread.getChannel(self.name)
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">self:push</span><span class="hljs-params">(v)</span></span>
self.chan:push(v)
<span class="hljs-keyword">end</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">self:pop</span><span class="hljs-params">()</span></span>
<span class="hljs-keyword">return</span> self.chan:pop()
<span class="hljs-keyword">end</span>
GLOBAL[self.name]=self
<span class="hljs-keyword">return</span> self
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">return</span> c
<span class="hljs-keyword">else</span>
<span class="hljs-built_in">error</span>(<span class="hljs-string">"Make sure you required the love.thread module!"</span>)
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">else</span>
c.linda=lanes.linda()
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">c:push</span><span class="hljs-params">(v)</span></span>
self.linda:send(<span class="hljs-string">"Q"</span>,v)
<span class="hljs-keyword">end</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">c:pop</span><span class="hljs-params">()</span></span>
<span class="hljs-keyword">return</span> ({self.linda:receive(<span class="hljs-number">0</span>,<span class="hljs-string">"Q"</span>)})[<span class="hljs-number">2</span>]
<span class="hljs-keyword">end</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">c:init</span><span class="hljs-params">()</span></span>
<span class="hljs-keyword">return</span> self
<span class="hljs-keyword">end</span>
GLOBAL[name]=c
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">return</span> c
<span class="hljs-keyword">end</span>
queue=multi:newSystemThreadedQueue(<span class="hljs-string">"QUEUE"</span>):init()
queue:push(<span class="hljs-string">"This is a test"</span>)
queue:push(<span class="hljs-string">"This is a test2"</span>)
queue:push(<span class="hljs-string">"This is a test3"</span>)
queue:push(<span class="hljs-string">"This is a test4"</span>)
multi:newSystemThread(<span class="hljs-string">"test2"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
queue=sThread.waitFor(<span class="hljs-string">"QUEUE"</span>):init()
data=queue:pop()
<span class="hljs-keyword">while</span> data <span class="hljs-keyword">do</span>
<span class="hljs-built_in">print</span>(data)
data=queue:pop()
<span class="hljs-keyword">end</span>
queue:push(<span class="hljs-string">"DONE!"</span>)
<span class="hljs-keyword">end</span>)
multi:newThread(<span class="hljs-string">"test!"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
thread.hold(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> <span class="hljs-keyword">return</span> queue:pop() <span class="hljs-keyword">end</span>)
t.text=<span class="hljs-string">"Done!"</span>
<span class="hljs-keyword">end</span>)
t=gui:newTextLabel(<span class="hljs-string">"no done yet!"</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">300</span>,<span class="hljs-number">100</span>)
t:centerX()
t:centerY()
</code></pre><h1 id="in-lanes"><a name="in-lanes" href="#in-lanes"></a>In Lanes</h1><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- The code is compatible with each other, I just wanted to show different things you can do in both examples
-- This file can be found in the examples folder as lanesintegrationtest4.lua
local GLOBAL,sThread=require(&quot;multi.integration.lanesManager&quot;).init()
queue=multi:newSystemThreadedQueue(&quot;QUEUE&quot;):init()
queue:push(&quot;This is a test&quot;)
queue:push(&quot;This is a test2&quot;)
queue:push(&quot;This is a test3&quot;)
queue:push(&quot;This is a test4&quot;)
multi:newSystemThread(&quot;test2&quot;,function()
queue=sThread.waitFor(&quot;QUEUE&quot;):init()
data=queue:pop()
while data do
print(data)
data=queue:pop()
end
queue:push(&quot;This is a test5&quot;)
queue:push(&quot;This is a test6&quot;)
queue:push(&quot;This is a test7&quot;)
queue:push(&quot;This is a test8&quot;)
end)
multi:newThread(&quot;test!&quot;,function() -- this is a lua thread
thread.sleep(.1)
data=queue:pop()
while data do
print(data)
data=queue:pop()
end
end)
multi:mainloop()
</code></pre>"><span class="hljs-comment">-- The code is compatible with each other, I just wanted to show different things you can do in both examples</span>
<span class="hljs-comment">-- This file can be found in the examples folder as lanesintegrationtest4.lua</span>
<span class="hljs-keyword">local</span> GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.lanesManager"</span>).init()
queue=multi:newSystemThreadedQueue(<span class="hljs-string">"QUEUE"</span>):init()
queue:push(<span class="hljs-string">"This is a test"</span>)
queue:push(<span class="hljs-string">"This is a test2"</span>)
queue:push(<span class="hljs-string">"This is a test3"</span>)
queue:push(<span class="hljs-string">"This is a test4"</span>)
multi:newSystemThread(<span class="hljs-string">"test2"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
queue=sThread.waitFor(<span class="hljs-string">"QUEUE"</span>):init()
data=queue:pop()
<span class="hljs-keyword">while</span> data <span class="hljs-keyword">do</span>
<span class="hljs-built_in">print</span>(data)
data=queue:pop()
<span class="hljs-keyword">end</span>
queue:push(<span class="hljs-string">"This is a test5"</span>)
queue:push(<span class="hljs-string">"This is a test6"</span>)
queue:push(<span class="hljs-string">"This is a test7"</span>)
queue:push(<span class="hljs-string">"This is a test8"</span>)
<span class="hljs-keyword">end</span>)
multi:newThread(<span class="hljs-string">"test!"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> <span class="hljs-comment">-- this is a lua thread</span>
thread.sleep(.<span class="hljs-number">1</span>)
data=queue:pop()
<span class="hljs-keyword">while</span> data <span class="hljs-keyword">do</span>
<span class="hljs-built_in">print</span>(data)
data=queue:pop()
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>)
multi:mainloop()
</code></pre><h2 id="update:-1.7.6"><a name="update:-1.7.6" href="#update:-1.7.6"></a>Update: 1.7.6</h2><p>Fixed:<br>Typos like always<br>Added:<br><br>multi:getPlatform() — returns “love2d” if using the love2d platform or returns “lanes” if using lanes for threading<br><br>examples files<br><br>In Events added method setTask(func)<br><br>The old way still works and is more convient to be honest, but I felt a method to do this was ok.<br></p><p>Updated:<br>some example files to reflect changes to the core. Changes allow for less typing<br><br>loveManager to require the compat if used so you dont need 2 require line to retrieve the library<br></p><h2 id="update:-1.7.5"><a name="update:-1.7.5" href="#update:-1.7.5"></a>Update: 1.7.5</h2><p>Fixed some typos in the readme… (I am sure there are more there are always more)<br><br>Added more features for module support<br><br>TODO:<br><br>Work on performance of the library… I see 3 places where I can make this thing run quicker<br></p><p>Ill show case some old versions of the multitasking library eventually so you can see its changes in days past!<br></p><h2 id="update:-1.7.4"><a name="update:-1.7.4" href="#update:-1.7.4"></a>Update: 1.7.4</h2><p>Added: the example folder which will be populated with more examples in the near future!<br><br>The loveManager integration that mimics the lanesManager integration almost exactly to keep coding in both enviroments as close to possible. This is done mostly for library creation support!<br><br>An example of the loveManager in action using almost the same code as the lanesintergreationtest2.lua<br><br>NOTE: This code has only been tested to work on love2d version 1.10.2 thoough it should work version 0.9.0</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>require(&quot;core.Library&quot;) -- Didn't add this to a repo yet! Will do eventually... Allows for injections and other cool things
require(&quot;multi.compat.love2d&quot;) -- allows for multitasking and binds my libraies to the love2d engine that i am using
GLOBAL,sThread=require(&quot;multi.integration.loveManager&quot;).init() -- load the love2d version of the lanesManager
--IMPORTANT
-- Do not make the above local, this is the one difference that the lanesManager does not have
-- If these are local the functions will have the upvalues put into them that do not exist on the threaded side
-- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though
-- Also each thread has a .1 second delay! This is used to generate a random values for each thread!
require(&quot;core.GuiManager&quot;) -- allows the use of graphics in the program.
gui.ff.Color=Color.Black
function comma_value(amount)
local formatted = amount
while true do
formatted, k = string.gsub(formatted, &quot;^(-?%d+)(%d%d%d)&quot;, '%1,%2')
if (k==0) then
break
end
end
return formatted
end
multi:newSystemThread(&quot;test1&quot;,function() -- Another difference is that the multi library is already loaded in the threaded enviroment as well as a call to multi:mainloop()
multi:benchMark(sThread.waitFor(&quot;Bench&quot;),nil,&quot;Thread 1&quot;):OnBench(function(self,c) GLOBAL[&quot;T1&quot;]=c multi:Stop() end)
end)
multi:newSystemThread(&quot;test2&quot;,function() -- spawns a thread in another lua process
multi:benchMark(sThread.waitFor(&quot;Bench&quot;),nil,&quot;Thread 2&quot;):OnBench(function(self,c) GLOBAL[&quot;T2&quot;]=c multi:Stop() end)
end)
multi:newSystemThread(&quot;test3&quot;,function() -- spawns a thread in another lua process
multi:benchMark(sThread.waitFor(&quot;Bench&quot;),nil,&quot;Thread 3&quot;):OnBench(function(self,c) GLOBAL[&quot;T3&quot;]=c multi:Stop() end)
end)
multi:newSystemThread(&quot;test4&quot;,function() -- spawns a thread in another lua process
multi:benchMark(sThread.waitFor(&quot;Bench&quot;),nil,&quot;Thread 4&quot;):OnBench(function(self,c) GLOBAL[&quot;T4&quot;]=c multi:Stop() end)
end)
multi:newSystemThread(&quot;test5&quot;,function() -- spawns a thread in another lua process
multi:benchMark(sThread.waitFor(&quot;Bench&quot;),nil,&quot;Thread 5&quot;):OnBench(function(self,c) GLOBAL[&quot;T5&quot;]=c multi:Stop() end)
end)
multi:newSystemThread(&quot;test6&quot;,function() -- spawns a thread in another lua process
multi:benchMark(sThread.waitFor(&quot;Bench&quot;),nil,&quot;Thread 6&quot;):OnBench(function(self,c) GLOBAL[&quot;T6&quot;]=c multi:Stop() end)
end)
multi:newSystemThread(&quot;Combiner&quot;,function() -- spawns a thread in another lua process
function comma_value(amount)
local formatted = amount
while true do
formatted, k = string.gsub(formatted, &quot;^(-?%d+)(%d%d%d)&quot;, '%1,%2')
if (k==0) then
break
end
end
return formatted
end
local b=comma_value(tostring(sThread.waitFor(&quot;T1&quot;)+sThread.waitFor(&quot;T2&quot;)+sThread.waitFor(&quot;T3&quot;)+sThread.waitFor(&quot;T4&quot;)+sThread.waitFor(&quot;T5&quot;)+sThread.waitFor(&quot;T6&quot;)))
GLOBAL[&quot;DONE&quot;]=b
end)
multi:newThread(&quot;test0&quot;,function()
-- sThread.waitFor(&quot;DONE&quot;) -- lets hold the main thread completely so we don't eat up cpu
-- os.exit()
-- when the main thread is holding there is a chance that error handling on the system threads may not work!
-- instead we can do this
while true do
thread.skip(1) -- allow error handling to take place... Otherwise lets keep the main thread running on the low
-- Before we held just because we could... But this is a game and we need to have logic continue
--sThreadM.sleep(.001) -- Sleeping for .001 is a greeat way to keep cpu usage down. Make sure if you aren't doing work to rest. Abuse the hell out of GLOBAL if you need to :P
if GLOBAL[&quot;DONE&quot;] then
t.text=&quot;Bench: &quot;..GLOBAL[&quot;DONE&quot;]
end
end
end)
GLOBAL[&quot;Bench&quot;]=3
t=gui:newTextLabel(&quot;no done yet!&quot;,0,0,300,100)
t:centerX()
t:centerY()
</code></pre>"><span class="hljs-built_in">require</span>(<span class="hljs-string">"core.Library"</span>) <span class="hljs-comment">-- Didn't add this to a repo yet! Will do eventually... Allows for injections and other cool things</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.compat.love2d"</span>) <span class="hljs-comment">-- allows for multitasking and binds my libraies to the love2d engine that i am using</span>
GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.loveManager"</span>).init() <span class="hljs-comment">-- load the love2d version of the lanesManager</span>
<span class="hljs-comment">--IMPORTANT</span>
<span class="hljs-comment">-- Do not make the above local, this is the one difference that the lanesManager does not have</span>
<span class="hljs-comment">-- If these are local the functions will have the upvalues put into them that do not exist on the threaded side</span>
<span class="hljs-comment">-- You will need to ensure that the function does not refer to any upvalues in its code. It will print an error if it does though</span>
<span class="hljs-comment">-- Also each thread has a .1 second delay! This is used to generate a random values for each thread!</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"core.GuiManager"</span>) <span class="hljs-comment">-- allows the use of graphics in the program.</span>
gui.ff.Color=Color.Black
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">comma_value</span><span class="hljs-params">(amount)</span></span>
<span class="hljs-keyword">local</span> formatted = amount
<span class="hljs-keyword">while</span> <span class="hljs-keyword">true</span> <span class="hljs-keyword">do</span>
formatted, k = <span class="hljs-built_in">string</span>.gsub(formatted, <span class="hljs-string">"^(-?%d+)(%d%d%d)"</span>, <span class="hljs-string">'%1,%2'</span>)
<span class="hljs-keyword">if</span> (k==<span class="hljs-number">0</span>) <span class="hljs-keyword">then</span>
<span class="hljs-keyword">break</span>
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">return</span> formatted
<span class="hljs-keyword">end</span>
multi:newSystemThread(<span class="hljs-string">"test1"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> <span class="hljs-comment">-- Another difference is that the multi library is already loaded in the threaded enviroment as well as a call to multi:mainloop()</span>
multi:benchMark(sThread.waitFor(<span class="hljs-string">"Bench"</span>),<span class="hljs-keyword">nil</span>,<span class="hljs-string">"Thread 1"</span>):OnBench(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self,c)</span></span> GLOBAL[<span class="hljs-string">"T1"</span>]=c multi:Stop() <span class="hljs-keyword">end</span>)
<span class="hljs-keyword">end</span>)
multi:newSystemThread(<span class="hljs-string">"test2"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> <span class="hljs-comment">-- spawns a thread in another lua process</span>
multi:benchMark(sThread.waitFor(<span class="hljs-string">"Bench"</span>),<span class="hljs-keyword">nil</span>,<span class="hljs-string">"Thread 2"</span>):OnBench(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self,c)</span></span> GLOBAL[<span class="hljs-string">"T2"</span>]=c multi:Stop() <span class="hljs-keyword">end</span>)
<span class="hljs-keyword">end</span>)
multi:newSystemThread(<span class="hljs-string">"test3"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> <span class="hljs-comment">-- spawns a thread in another lua process</span>
multi:benchMark(sThread.waitFor(<span class="hljs-string">"Bench"</span>),<span class="hljs-keyword">nil</span>,<span class="hljs-string">"Thread 3"</span>):OnBench(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self,c)</span></span> GLOBAL[<span class="hljs-string">"T3"</span>]=c multi:Stop() <span class="hljs-keyword">end</span>)
<span class="hljs-keyword">end</span>)
multi:newSystemThread(<span class="hljs-string">"test4"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> <span class="hljs-comment">-- spawns a thread in another lua process</span>
multi:benchMark(sThread.waitFor(<span class="hljs-string">"Bench"</span>),<span class="hljs-keyword">nil</span>,<span class="hljs-string">"Thread 4"</span>):OnBench(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self,c)</span></span> GLOBAL[<span class="hljs-string">"T4"</span>]=c multi:Stop() <span class="hljs-keyword">end</span>)
<span class="hljs-keyword">end</span>)
multi:newSystemThread(<span class="hljs-string">"test5"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> <span class="hljs-comment">-- spawns a thread in another lua process</span>
multi:benchMark(sThread.waitFor(<span class="hljs-string">"Bench"</span>),<span class="hljs-keyword">nil</span>,<span class="hljs-string">"Thread 5"</span>):OnBench(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self,c)</span></span> GLOBAL[<span class="hljs-string">"T5"</span>]=c multi:Stop() <span class="hljs-keyword">end</span>)
<span class="hljs-keyword">end</span>)
multi:newSystemThread(<span class="hljs-string">"test6"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> <span class="hljs-comment">-- spawns a thread in another lua process</span>
multi:benchMark(sThread.waitFor(<span class="hljs-string">"Bench"</span>),<span class="hljs-keyword">nil</span>,<span class="hljs-string">"Thread 6"</span>):OnBench(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self,c)</span></span> GLOBAL[<span class="hljs-string">"T6"</span>]=c multi:Stop() <span class="hljs-keyword">end</span>)
<span class="hljs-keyword">end</span>)
multi:newSystemThread(<span class="hljs-string">"Combiner"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> <span class="hljs-comment">-- spawns a thread in another lua process</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">comma_value</span><span class="hljs-params">(amount)</span></span>
<span class="hljs-keyword">local</span> formatted = amount
<span class="hljs-keyword">while</span> <span class="hljs-keyword">true</span> <span class="hljs-keyword">do</span>
formatted, k = <span class="hljs-built_in">string</span>.gsub(formatted, <span class="hljs-string">"^(-?%d+)(%d%d%d)"</span>, <span class="hljs-string">'%1,%2'</span>)
<span class="hljs-keyword">if</span> (k==<span class="hljs-number">0</span>) <span class="hljs-keyword">then</span>
<span class="hljs-keyword">break</span>
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">return</span> formatted
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">local</span> b=comma_value(<span class="hljs-built_in">tostring</span>(sThread.waitFor(<span class="hljs-string">"T1"</span>)+sThread.waitFor(<span class="hljs-string">"T2"</span>)+sThread.waitFor(<span class="hljs-string">"T3"</span>)+sThread.waitFor(<span class="hljs-string">"T4"</span>)+sThread.waitFor(<span class="hljs-string">"T5"</span>)+sThread.waitFor(<span class="hljs-string">"T6"</span>)))
GLOBAL[<span class="hljs-string">"DONE"</span>]=b
<span class="hljs-keyword">end</span>)
multi:newThread(<span class="hljs-string">"test0"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-comment">-- sThread.waitFor("DONE") -- lets hold the main thread completely so we don't eat up cpu</span>
<span class="hljs-comment">-- os.exit()</span>
<span class="hljs-comment">-- when the main thread is holding there is a chance that error handling on the system threads may not work!</span>
<span class="hljs-comment">-- instead we can do this</span>
<span class="hljs-keyword">while</span> <span class="hljs-keyword">true</span> <span class="hljs-keyword">do</span>
thread.skip(<span class="hljs-number">1</span>) <span class="hljs-comment">-- allow error handling to take place... Otherwise lets keep the main thread running on the low</span>
<span class="hljs-comment">-- Before we held just because we could... But this is a game and we need to have logic continue</span>
<span class="hljs-comment">--sThreadM.sleep(.001) -- Sleeping for .001 is a greeat way to keep cpu usage down. Make sure if you aren't doing work to rest. Abuse the hell out of GLOBAL if you need to :P</span>
<span class="hljs-keyword">if</span> GLOBAL[<span class="hljs-string">"DONE"</span>] <span class="hljs-keyword">then</span>
t.text=<span class="hljs-string">"Bench: "</span>..GLOBAL[<span class="hljs-string">"DONE"</span>]
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>
<span class="hljs-keyword">end</span>)
GLOBAL[<span class="hljs-string">"Bench"</span>]=<span class="hljs-number">3</span>
t=gui:newTextLabel(<span class="hljs-string">"no done yet!"</span>,<span class="hljs-number">0</span>,<span class="hljs-number">0</span>,<span class="hljs-number">300</span>,<span class="hljs-number">100</span>)
t:centerX()
t:centerY()
</code></pre><h2 id="update:-1.7.3"><a name="update:-1.7.3" href="#update:-1.7.3"></a>Update: 1.7.3</h2><p>Changed how requiring the library works!<br><code>require("multi.all")</code> Will still work as expected; however, with the exception of threading, compat, and integrations everything else has been moved into the core of the library.</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- This means that these are no longer required and will cause an error if done so
require(&quot;multi.loop&quot;)
require(&quot;multi.alarm&quot;)
require(&quot;multi.updater&quot;)
require(&quot;multi.tloop&quot;)
require(&quot;multi.watcher&quot;)
require(&quot;multi.tstep&quot;)
require(&quot;multi.step&quot;)
require(&quot;multi.task&quot;)
-- ^ they are all part of the core now
</code></pre>"><span class="hljs-comment">-- This means that these are no longer required and will cause an error if done so</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.loop"</span>)
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.alarm"</span>)
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.updater"</span>)
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.tloop"</span>)
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.watcher"</span>)
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.tstep"</span>)
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.step"</span>)
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.task"</span>)
<span class="hljs-comment">-- ^ they are all part of the core now</span>
</code></pre><h2 id="update:-1.7.2"><a name="update:-1.7.2" href="#update:-1.7.2"></a>Update: 1.7.2</h2><p>Moved updaters, loops, and alarms into the init.lua file. I consider them core features and they are referenced in the init.lua file so they need to exist there. Threaded versions are still separate though. Added another example file</p><h2 id="update:-1.7.1-bug-fixes-only"><a name="update:-1.7.1-bug-fixes-only" href="#update:-1.7.1-bug-fixes-only"></a>Update: 1.7.1 Bug Fixes Only</h2><h2 id="update:-1.7.0"><a name="update:-1.7.0" href="#update:-1.7.0"></a>Update: 1.7.0</h2><p>Modified: multi.integration.lanesManager.lua<br>It is now in a stable and simple state Works with the latest lanes version! Tested with version 3.11 I cannot promise that everything will work with eariler versions. Future versions are good though.<br><br>Example Usage:<br><br>sThread is a handle to a global interface for system threads to interact with themself<br><br>thread is the interface for multithreads as seen in the threading section<br></p><p>GLOBAL a table that can be used throughout each and every thread</p><p>sThreads have a few methods<br><br>sThread.set(name,val) — you can use the GLOBAL table instead modifies the same table anyway<br><br>sThread.get(name) — you can use the GLOBAL table instead modifies the same table anyway<br><br>sThread.waitFor(name) — waits until a value exists, if it does it returns it<br><br>sThread.getCores() — returns the number of cores on your cpu<br><br>sThread.sleep(n) — sleeps for a bit stopping the entire thread from running<br><br>sThread.hold(n) — sleeps until a condition is met<br></p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>local GLOBAL,sThread=require(&quot;multi.integration.lanesManager&quot;).init()
require(&quot;multi.all&quot;)
multi:newAlarm(2):OnRing(function(self)
GLOBAL[&quot;NumOfCores&quot;]=sThread.getCores()
end)
multi:newAlarm(7):OnRing(function(self)
GLOBAL[&quot;AnotherTest&quot;]=true
end)
multi:newAlarm(13):OnRing(function(self)
GLOBAL[&quot;FinalTest&quot;]=true
end)
multi:newSystemThread(&quot;test&quot;,function() -- spawns a thread in another lua process
require(&quot;multi.all&quot;) -- now you can do all of your coding with the multi library! You could even spawn more threads from here with the integration. You would need to require the interaction again though
print(&quot;Waiting for variable: NumOfCores&quot;)
print(&quot;Got it: &quot;,sThread.waitFor(&quot;NumOfCores&quot;))
sThread.hold(function()
return GLOBAL[&quot;AnotherTest&quot;] -- note this would hold the entire systemthread. Spawn a coroutine thread using multi:newThread() or multi:newThreaded...
end)
print(&quot;Holding works!&quot;)
multi:newThread(&quot;tests&quot;,function()
thread.hold(function()
return GLOBAL[&quot;FinalTest&quot;] -- note this will not hold the entire systemthread. As seen with the TLoop constantly going!
end)
print(&quot;Final test works!&quot;)
os.exit()
end)
local a=0
multi:newTLoop(function()
a=a+1
print(a)
end,.5)
multi:mainloop()
end)
multi:mainloop()
</code></pre>"><span class="hljs-keyword">local</span> GLOBAL,sThread=<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.integration.lanesManager"</span>).init()
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.all"</span>)
multi:newAlarm(<span class="hljs-number">2</span>):OnRing(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self)</span></span>
GLOBAL[<span class="hljs-string">"NumOfCores"</span>]=sThread.getCores()
<span class="hljs-keyword">end</span>)
multi:newAlarm(<span class="hljs-number">7</span>):OnRing(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self)</span></span>
GLOBAL[<span class="hljs-string">"AnotherTest"</span>]=<span class="hljs-keyword">true</span>
<span class="hljs-keyword">end</span>)
multi:newAlarm(<span class="hljs-number">13</span>):OnRing(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self)</span></span>
GLOBAL[<span class="hljs-string">"FinalTest"</span>]=<span class="hljs-keyword">true</span>
<span class="hljs-keyword">end</span>)
multi:newSystemThread(<span class="hljs-string">"test"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span> <span class="hljs-comment">-- spawns a thread in another lua process</span>
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.all"</span>) <span class="hljs-comment">-- now you can do all of your coding with the multi library! You could even spawn more threads from here with the integration. You would need to require the interaction again though</span>
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Waiting for variable: NumOfCores"</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Got it: "</span>,sThread.waitFor(<span class="hljs-string">"NumOfCores"</span>))
sThread.hold(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-keyword">return</span> GLOBAL[<span class="hljs-string">"AnotherTest"</span>] <span class="hljs-comment">-- note this would hold the entire systemthread. Spawn a coroutine thread using multi:newThread() or multi:newThreaded...</span>
<span class="hljs-keyword">end</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Holding works!"</span>)
multi:newThread(<span class="hljs-string">"tests"</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
thread.hold(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
<span class="hljs-keyword">return</span> GLOBAL[<span class="hljs-string">"FinalTest"</span>] <span class="hljs-comment">-- note this will not hold the entire systemthread. As seen with the TLoop constantly going!</span>
<span class="hljs-keyword">end</span>)
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Final test works!"</span>)
<span class="hljs-built_in">os</span>.exit()
<span class="hljs-keyword">end</span>)
<span class="hljs-keyword">local</span> a=<span class="hljs-number">0</span>
multi:newTLoop(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span></span>
a=a+<span class="hljs-number">1</span>
<span class="hljs-built_in">print</span>(a)
<span class="hljs-keyword">end</span>,.<span class="hljs-number">5</span>)
multi:mainloop()
<span class="hljs-keyword">end</span>)
multi:mainloop()
</code></pre><h2 id="update:-1.6.0"><a name="update:-1.6.0" href="#update:-1.6.0"></a>Update: 1.6.0</h2><p>Changed: steps and loops</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>-- Was
step:OnStep(function(pos,self) -- same goes for tsteps as well
print(pos)
end)
multi:newLoop(function(dt,self)
print(dt)
end)
-- Is now
step:OnStep(function(self,pos) -- same goes for tsteps as well
print(pos)
end)
multi:newLoop(function(self,dt)
print(dt)
end)
</code></pre>"><span class="hljs-comment">-- Was</span>
step:OnStep(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(pos,self)</span></span> <span class="hljs-comment">-- same goes for tsteps as well</span>
<span class="hljs-built_in">print</span>(pos)
<span class="hljs-keyword">end</span>)
multi:newLoop(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(dt,self)</span></span>
<span class="hljs-built_in">print</span>(dt)
<span class="hljs-keyword">end</span>)
<span class="hljs-comment">-- Is now</span>
step:OnStep(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self,pos)</span></span> <span class="hljs-comment">-- same goes for tsteps as well</span>
<span class="hljs-built_in">print</span>(pos)
<span class="hljs-keyword">end</span>)
multi:newLoop(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(self,dt)</span></span>
<span class="hljs-built_in">print</span>(dt)
<span class="hljs-keyword">end</span>)
</code></pre><p>Reasoning I wanted to keep objects consistant, but a lot of my older libraries use the old way of doing things. Therefore I added a backwards module</p><pre class="lua hljs"><code class="lua" data-origin="<pre><code class=&quot;lua&quot;>require(&quot;multi.all&quot;)
require(&quot;multi.compat.backwards[1,5,0]&quot;) -- allows for the use of features that were scrapped/changed in 1.6.0+
</code></pre>"><span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.all"</span>)
<span class="hljs-built_in">require</span>(<span class="hljs-string">"multi.compat.backwards[1,5,0]"</span>) <span class="hljs-comment">-- allows for the use of features that were scrapped/changed in 1.6.0+</span>
</code></pre><h2 id="update:-1.5.0"><a name="update:-1.5.0" href="#update:-1.5.0"></a>Update: 1.5.0</h2><p>Added:</p><ul>
<li>An easy way to manage timeouts</li><li>Small bug fixes</li></ul><h2 id="update:-1.4.1---first-public-release-of-the-library"><a name="update:-1.4.1---first-public-release-of-the-library" href="#update:-1.4.1---first-public-release-of-the-library"></a>Update: 1.4.1 - First Public release of the library</h2><p><strong>IMPORTANT:</strong><br>Every update I make aims to make things simpler more efficent and just better, but a lot of old code, which can be really big, uses a lot of older features. I know the pain of having to rewrite everything. My promise to my library users is that I will always have backwards support for older features! New ways may exist that are quicker and eaiser, but the old features/methods will be supported.<br></p>
<footer style="position:fixed; font-size:.8em; text-align:right; bottom:0px; margin-left:-25px; height:20px; width:100%;">generated by <a href="http://pad.haroopress.com" target="_blank">haroopad</a></footer>
</body>
</html>