Angelscript/docs/manual/doc_adv_timeout.html

192 lines
13 KiB
HTML

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.18"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>AngelScript: Timeout long running scripts</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function() { init_search(); });
/* @license-end */
</script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
<tbody>
<tr style="height: 56px;">
<td id="projectlogo"><img alt="Logo" src="aslogo_small.png"/></td>
<td id="projectalign" style="padding-left: 0.5em;">
<div id="projectname">AngelScript
</div>
</td>
<td> <div id="MSearchBox" class="MSearchBoxInactive">
<span class="left">
<img id="MSearchSelect" src="search/mag_sel.png"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
alt=""/>
<input type="text" id="MSearchField" value="Search" accesskey="S"
onfocus="searchBox.OnSearchFieldFocus(true)"
onblur="searchBox.OnSearchFieldFocus(false)"
onkeyup="searchBox.OnSearchFieldChange(event)"/>
</span><span class="right">
<a id="MSearchClose" href="javascript:searchBox.CloseResultsWindow()"><img id="MSearchCloseImg" border="0" src="search/close.png" alt=""/></a>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.18 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
<div id="nav-tree">
<div id="nav-tree-contents">
<div id="nav-sync" class="sync"></div>
</div>
</div>
<div id="splitbar" style="-moz-user-select:none;"
class="ui-resizable-handle">
</div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('doc_adv_timeout.html',''); initResizable(); });
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
onmouseover="return searchBox.OnSearchSelectShow()"
onmouseout="return searchBox.OnSearchSelectHide()"
onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>
<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0"
name="MSearchResults" id="MSearchResults">
</iframe>
</div>
<div class="PageDoc"><div class="header">
<div class="headertitle">
<div class="title">Timeout long running scripts </div> </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>To prevent long running scripts to freeze the application it may be necessary to add a way to timeout the execution. This article presents two different ways to do so.</p>
<h1><a class="anchor" id="doc_adv_timeout_1"></a>
With the line callback</h1>
<p>The line callback feature can be used to perform some special treatment during execution of the scripts. The callback is called for every script statement, which makes it possible to verify if the script has <br />
executed for too long time and if so suspend the execution to be resumed at a later time.</p>
<p>Before calling the context's <a class="el" href="classas_i_script_context.html#a8e52894432737acac2e1a422e496bf84">Execute</a> method, set the callback function like so:</p>
<div class="fragment"><div class="line"><span class="keywordtype">int</span> ExecuteScriptWithTimeOut(<a class="code" href="classas_i_script_context.html">asIScriptContext</a> *ctx)</div>
<div class="line">{</div>
<div class="line"> <span class="comment">// Define the timeout as 1 second</span></div>
<div class="line"> DWORD timeOut = timeGetTime() + 1000;</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Set up the line callback that will timout the script</span></div>
<div class="line"> ctx-&gt;<a class="code" href="classas_i_script_context.html#ae2747f643bf9a07364f922c460ef57dd">SetLineCallback</a>(<a class="code" href="angelscript_8h.html#a78f8f2c7f1c88b12e74a5ac47b4184ae">asFUNCTION</a>(LineCallback), &amp;timeOut, <a class="code" href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4a68ae43cc91cdfc3fa4590c9e6164e4f4">asCALL_CDECL</a>);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Execute the script</span></div>
<div class="line"> <span class="keywordtype">int</span> status = ctx-&gt;<a class="code" href="classas_i_script_context.html#a8e52894432737acac2e1a422e496bf84">Execute</a>();</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// If the status is asEXECUTION_SUSPENDED the script can</span></div>
<div class="line"> <span class="comment">// be resumed by calling this function again.</span></div>
<div class="line"> <span class="keywordflow">return</span> status;</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="comment">// The line callback function is called by the VM for each statement that is executed</span></div>
<div class="line"><span class="keywordtype">void</span> LineCallback(<a class="code" href="classas_i_script_context.html">asIScriptContext</a> *ctx, DWORD *timeOut)</div>
<div class="line">{</div>
<div class="line"> <span class="comment">// If the time out is reached we suspend the script</span></div>
<div class="line"> <span class="keywordflow">if</span>( *timeOut &lt; timeGetTime() )</div>
<div class="line"> ctx-&gt;<a class="code" href="classas_i_script_context.html#ad4ac8be3586c46069b5870e40c86544a">Suspend</a>();</div>
<div class="line">}</div>
</div><!-- fragment --><p>Take a look at the sample <a class="el" href="doc_samples_events.html">Events</a> to see this working.</p>
<p>Observe that if the script is compiled with <a class="el" href="angelscript_8h.html#a53c2e8a74ade77c928316396394ebe0fa73b396e4ea6376f0962d19add962bd91">asEP_BUILD_WITHOUT_LINE_CUES</a>, the line callback will be invoked less frequently, though it is guaranteed to be invoked at least for every loop or function call.</p>
<h1><a class="anchor" id="doc_adv_timeout_2"></a>
With a secondary thread</h1>
<p>A second thread can be set up to suspend the execution after the timeout. This thread can then be put to sleep so that it doesn't impact performance during the execution. When the thread wakes up it should call the context's <a class="el" href="classas_i_script_context.html#ad4ac8be3586c46069b5870e40c86544a">Suspend</a> method.</p>
<p>The below shows some possible code for doing this. Note that the code for setting up the thread is fictive, as this is different for each target OS.</p>
<div class="fragment"><div class="line"><span class="comment">// The variables that are shared between the threads</span></div>
<div class="line"><a class="code" href="classas_i_script_context.html">asIScriptContext</a> *threadCtx;</div>
<div class="line"><span class="keywordtype">int</span> threadId;</div>
<div class="line"> </div>
<div class="line"><span class="comment">// This function will be executed in the secondary thread</span></div>
<div class="line"><span class="keywordtype">void</span> SuspendThread()</div>
<div class="line">{</div>
<div class="line"> <span class="comment">// Put the thread to sleep until the timeout (1 second)</span></div>
<div class="line"> Sleep(1000);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// When we wake-up we call the context&#39;s Suspend method</span></div>
<div class="line"> ctx-&gt;<a class="code" href="classas_i_script_context.html#ad4ac8be3586c46069b5870e40c86544a">Suspend</a>();</div>
<div class="line">}</div>
<div class="line"> </div>
<div class="line"><span class="comment">// This function sets up the timeout thread and executes the script</span></div>
<div class="line"><span class="keywordtype">int</span> ExecuteScriptWithTimeOut(<a class="code" href="classas_i_script_context.html">asIScriptContext</a> *ctx)</div>
<div class="line">{</div>
<div class="line"> <span class="comment">// Set the shared context pointer before creating the thread</span></div>
<div class="line"> threadCtx = ctx;</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Create the thread that will immediately go to sleep</span></div>
<div class="line"> threadId = CreateThread(SuspendThread);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Execute the script</span></div>
<div class="line"> <span class="keywordtype">int</span> status = ctx-&gt;<a class="code" href="classas_i_script_context.html#a8e52894432737acac2e1a422e496bf84">Execute</a>();</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Destroy the secondary thread before releasing the context</span></div>
<div class="line"> DestroyThread(threadId);</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// Clear the global variables</span></div>
<div class="line"> threadId = 0;</div>
<div class="line"> threadCtx = 0;</div>
<div class="line"> </div>
<div class="line"> <span class="comment">// If the status is asEXECUTION_SUSPENDED the script can</span></div>
<div class="line"> <span class="comment">// be resumed by calling this function again.</span></div>
<div class="line"> </div>
<div class="line"> <span class="keywordflow">return</span> status;</div>
<div class="line">}</div>
</div><!-- fragment --><p>Observe that this way of doing it is safe even if the AngelScript library has been built without <a class="el" href="doc_adv_multithread.html">multithread support</a>. </p>
</div></div><!-- contents -->
</div><!-- PageDoc -->
</div><!-- doc-content -->
<div class="ttc" id="aclassas_i_script_context_html"><div class="ttname"><a href="classas_i_script_context.html">asIScriptContext</a></div><div class="ttdoc">The interface to the virtual machine.</div><div class="ttdef"><b>Definition:</b> angelscript.h:2717</div></div>
<div class="ttc" id="aclassas_i_script_context_html_a8e52894432737acac2e1a422e496bf84"><div class="ttname"><a href="classas_i_script_context.html#a8e52894432737acac2e1a422e496bf84">asIScriptContext::Execute</a></div><div class="ttdeci">virtual int Execute()=0</div><div class="ttdoc">Executes the prepared function.</div></div>
<div class="ttc" id="aangelscript_8h_html_a78f8f2c7f1c88b12e74a5ac47b4184ae"><div class="ttname"><a href="angelscript_8h.html#a78f8f2c7f1c88b12e74a5ac47b4184ae">asFUNCTION</a></div><div class="ttdeci">#define asFUNCTION(f)</div><div class="ttdoc">Returns an asSFuncPtr representing the function specified by the name.</div><div class="ttdef"><b>Definition:</b> angelscript.h:675</div></div>
<div class="ttc" id="aclassas_i_script_context_html_ae2747f643bf9a07364f922c460ef57dd"><div class="ttname"><a href="classas_i_script_context.html#ae2747f643bf9a07364f922c460ef57dd">asIScriptContext::SetLineCallback</a></div><div class="ttdeci">virtual int SetLineCallback(asSFuncPtr callback, void *obj, int callConv)=0</div><div class="ttdoc">Sets a line callback function. The function will be called for each executed script statement.</div></div>
<div class="ttc" id="aclassas_i_script_context_html_ad4ac8be3586c46069b5870e40c86544a"><div class="ttname"><a href="classas_i_script_context.html#ad4ac8be3586c46069b5870e40c86544a">asIScriptContext::Suspend</a></div><div class="ttdeci">virtual int Suspend()=0</div><div class="ttdoc">Suspends the execution, which can then be resumed by calling Execute again.</div></div>
<div class="ttc" id="aangelscript_8h_html_a3ec92ea3c4762e44c2df788ceccdd1e4a68ae43cc91cdfc3fa4590c9e6164e4f4"><div class="ttname"><a href="angelscript_8h.html#a3ec92ea3c4762e44c2df788ceccdd1e4a68ae43cc91cdfc3fa4590c9e6164e4f4">asCALL_CDECL</a></div><div class="ttdeci">@ asCALL_CDECL</div><div class="ttdoc">A cdecl function.</div><div class="ttdef"><b>Definition:</b> angelscript.h:226</div></div>
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
<ul>
<li class="footer">Generated on Sat Dec 5 2020 23:20:24 for AngelScript by
<a href="http://www.doxygen.org/index.html">
<img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.18 </li>
</ul>
</div>
</body>
</html>