File: doc_adv_timeout.h

package info (click to toggle)
angelscript 2.38.0%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,736 kB
  • sloc: cpp: 77,114; asm: 2,017; makefile: 666; xml: 253; javascript: 42; ansic: 26; python: 22; sh: 7
file content (105 lines) | stat: -rw-r--r-- 3,327 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**

\page doc_adv_timeout Timeout long running scripts

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.

\section doc_adv_timeout_1 With the line callback

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  
executed for too long time and if so suspend the execution to be resumed at
a later time.

Before calling the context's \ref asIScriptContext::Execute "Execute" method, 
set the callback function like so:

\code
int ExecuteScriptWithTimeOut(asIScriptContext *ctx)
{
  // Define the timeout as 1 second
  DWORD timeOut = timeGetTime() + 1000;

  // Set up the line callback that will timout the script
  ctx->SetLineCallback(asFUNCTION(LineCallback), &timeOut, asCALL_CDECL);

  // Execute the script
  int status = ctx->Execute();

  // If the status is asEXECUTION_SUSPENDED the script can
  // be resumed by calling this function again.
  return status;
}

// The line callback function is called by the VM for each statement that is executed
void LineCallback(asIScriptContext *ctx, DWORD *timeOut)
{
  // If the time out is reached we suspend the script
  if( *timeOut < timeGetTime() )
    ctx->Suspend();
}
\endcode

Take a look at the sample \ref doc_samples_events to 
see this working.

Observe that if the script is compiled with \ref asEP_BUILD_WITHOUT_LINE_CUES, the line
callback will be invoked less frequently, though it is guaranteed to be invoked at least
for every loop or function call.

\section doc_adv_timeout_2 With a secondary thread

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 \ref asIScriptContext::Suspend "Suspend" method.

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.

\code
// The variables that are shared between the threads
asIScriptContext *threadCtx;
int threadId;

// This function will be executed in the secondary thread
void SuspendThread()
{
  // Put the thread to sleep until the timeout (1 second)
  Sleep(1000);
  
  // When we wake-up we call the context's Suspend method
  ctx->Suspend();
}

// This function sets up the timeout thread and executes the script
int ExecuteScriptWithTimeOut(asIScriptContext *ctx)
{
  // Set the shared context pointer before creating the thread
  threadCtx = ctx;

  // Create the thread that will immediately go to sleep
  threadId = CreateThread(SuspendThread);
  
  // Execute the script
  int status = ctx->Execute();
  
  // Destroy the secondary thread before releasing the context
  DestroyThread(threadId);
  
  // Clear the global variables
  threadId = 0;
  threadCtx = 0;
  
  // If the status is asEXECUTION_SUSPENDED the script can
  // be resumed by calling this function again.
  
  return status;
}
\endcode

Observe that this way of doing it is safe even if the AngelScript library has been
built without \ref doc_adv_multithread "multithread support". 
*/