📄 a00015.html
字号:
<span class="comment"> * Declaration of the protothread function implementing the code lock</span><span class="comment"> * logic. The protothread function is declared using the PT_THREAD()</span><span class="comment"> * macro. The function is declared with the "static" keyword since it</span><span class="comment"> * is local to this file. The name of the function is codelock_thread</span><span class="comment"> * and it takes one argument, pt, of the type struct pt.</span><span class="comment"> *</span><span class="comment"> */</span><span class="keyword">static</span><a class="code" href="a00014.html#g3d4c8bd4aada659eb34f5d2ffd3e7901">PT_THREAD</a>(codelock_thread(<span class="keyword">struct</span> pt *pt)){ <span class="comment">/* This is a local variable that holds the number of keys that have</span><span class="comment"> * been pressed. Note that it is declared with the "static" keyword</span><span class="comment"> * to make sure that the variable is *not* allocated on the stack.</span><span class="comment"> */</span> <span class="keyword">static</span> <span class="keywordtype">int</span> keys; <span class="comment">/*</span><span class="comment"> * Declare the beginning of the protothread.</span><span class="comment"> */</span> <a class="code" href="a00014.html#g2ffbb9e554e08a343ae2f9de4bedfdfc">PT_BEGIN</a>(pt); <span class="comment">/*</span><span class="comment"> * We'll let the protothread loop until the protothread is</span><span class="comment"> * expliticly exited with PT_EXIT().</span><span class="comment"> */</span> <span class="keywordflow">while</span>(1) { <span class="comment">/*</span><span class="comment"> * We'll be reading key presses until we get the right amount of</span><span class="comment"> * correct keys.</span><span class="comment"> */</span> <span class="keywordflow">for</span>(keys = 0; keys < <span class="keyword">sizeof</span>(code); ++keys) { <span class="comment">/*</span><span class="comment"> * If we haven't gotten any keypresses, we'll simply wait for one.</span><span class="comment"> */</span> <span class="keywordflow">if</span>(keys == 0) { <span class="comment">/*</span><span class="comment"> * The PT_WAIT_UNTIL() function will block until the condition</span><span class="comment"> * key_pressed() is true.</span><span class="comment"> */</span> <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, key_pressed()); } <span class="keywordflow">else</span> { <span class="comment">/*</span><span class="comment"> * If the "key" variable was larger than zero, we have already</span><span class="comment"> * gotten at least one correct key press. If so, we'll not</span><span class="comment"> * only wait for the next key, but we'll also set a timer that</span><span class="comment"> * expires in one second. This gives the person pressing the</span><span class="comment"> * keys one second to press the next key in the code.</span><span class="comment"> */</span> timer_set(&codelock_timer, 1000); <span class="comment">/*</span><span class="comment"> * The following statement shows how complex blocking</span><span class="comment"> * conditions can be easily expressed with protothreads and</span><span class="comment"> * the PT_WAIT_UNTIL() function.</span><span class="comment"> */</span> <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, key_pressed() || timer_expired(&codelock_timer)); <span class="comment">/*</span><span class="comment"> * If the timer expired, we should break out of the for() loop</span><span class="comment"> * and start reading keys from the beginning of the while(1)</span><span class="comment"> * loop instead.</span><span class="comment"> */</span> <span class="keywordflow">if</span>(timer_expired(&codelock_timer)) { printf(<span class="stringliteral">"Code lock timer expired.\n"</span>); <span class="comment">/*</span><span class="comment"> * Break out from the for() loop and start from the</span><span class="comment"> * beginning of the while(1) loop.</span><span class="comment"> */</span> <span class="keywordflow">break</span>; } } <span class="comment">/*</span><span class="comment"> * Check if the pressed key was correct.</span><span class="comment"> */</span> <span class="keywordflow">if</span>(key != code[keys]) { printf(<span class="stringliteral">"Incorrect key '%c' found\n"</span>, key); <span class="comment">/*</span><span class="comment"> * Break out of the for() loop since the key was incorrect.</span><span class="comment"> */</span> <span class="keywordflow">break</span>; } <span class="keywordflow">else</span> { printf(<span class="stringliteral">"Correct key '%c' found\n"</span>, key); } } <span class="comment">/*</span><span class="comment"> * Check if we have gotten all keys.</span><span class="comment"> */</span> <span class="keywordflow">if</span>(keys == <span class="keyword">sizeof</span>(code)) { printf(<span class="stringliteral">"Correct code entered, waiting for 500 ms before unlocking.\n"</span>); <span class="comment">/*</span><span class="comment"> * Ok, we got the correct code. But to make sure that the code</span><span class="comment"> * was not just a fluke of luck by an intruder, but the correct</span><span class="comment"> * code entered by a person that knows the correct code, we'll</span><span class="comment"> * wait for half a second before opening the lock. If another</span><span class="comment"> * key is pressed during this time, we'll assume that it was a</span><span class="comment"> * fluke of luck that the correct code was entered the first</span><span class="comment"> * time.</span><span class="comment"> */</span> timer_set(&codelock_timer, 500); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, key_pressed() || timer_expired(&codelock_timer)); <span class="comment">/*</span><span class="comment"> * If we continued from the PT_WAIT_UNTIL() statement without</span><span class="comment"> * the timer expired, we don't open the lock.</span><span class="comment"> */</span> <span class="keywordflow">if</span>(!timer_expired(&codelock_timer)) { printf(<span class="stringliteral">"Key pressed during final wait, code lock locked again.\n"</span>); } <span class="keywordflow">else</span> { <span class="comment">/*</span><span class="comment"> * If the timer expired, we'll open the lock and exit from the</span><span class="comment"> * protothread.</span><span class="comment"> */</span> printf(<span class="stringliteral">"Code lock unlocked.\n"</span>); <a class="code" href="a00014.html#g905451249dca72ce0385bf2a9ff178ee">PT_EXIT</a>(pt); } } } <span class="comment">/*</span><span class="comment"> * Finally, we'll mark the end of the protothread.</span><span class="comment"> */</span> <a class="code" href="a00014.html#g7b04a0035bef29d905496c23bae066d2">PT_END</a>(pt);}<span class="comment">/*---------------------------------------------------------------------------*/</span><span class="comment">/*</span><span class="comment"> * This is the second protothread in this example. It implements a</span><span class="comment"> * simulated user pressing the keys. This illustrates how a linear</span><span class="comment"> * sequence of timed instructions can be implemented with</span><span class="comment"> * protothreads.</span><span class="comment"> */</span><span class="keyword">static</span><a class="code" href="a00014.html#g3d4c8bd4aada659eb34f5d2ffd3e7901">PT_THREAD</a>(input_thread(<span class="keyword">struct</span> pt *pt)){ <a class="code" href="a00014.html#g2ffbb9e554e08a343ae2f9de4bedfdfc">PT_BEGIN</a>(pt); printf(<span class="stringliteral">"Waiting 1 second before entering first key.\n"</span>); timer_set(&input_timer, 1000); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'1'</span>); timer_set(&input_timer, 100); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'2'</span>); timer_set(&input_timer, 100); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'3'</span>); timer_set(&input_timer, 2000); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'1'</span>); timer_set(&input_timer, 200); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'4'</span>); timer_set(&input_timer, 200); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'2'</span>); timer_set(&input_timer, 2000); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'3'</span>); timer_set(&input_timer, 200); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'1'</span>); timer_set(&input_timer, 200); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'4'</span>); timer_set(&input_timer, 200); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'2'</span>); timer_set(&input_timer, 100); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'3'</span>); timer_set(&input_timer, 100); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'4'</span>); timer_set(&input_timer, 1500); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'1'</span>); timer_set(&input_timer, 300); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'4'</span>); timer_set(&input_timer, 400); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'2'</span>); timer_set(&input_timer, 500); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); press_key(<span class="charliteral">'3'</span>); timer_set(&input_timer, 2000); <a class="code" href="a00014.html#g99e43010ec61327164466aa2d902de45">PT_WAIT_UNTIL</a>(pt, timer_expired(&input_timer)); <a class="code" href="a00014.html#g7b04a0035bef29d905496c23bae066d2">PT_END</a>(pt);}<span class="comment">/*---------------------------------------------------------------------------*/</span><span class="comment">/*</span><span class="comment"> * This is the main function. It initializes the two protothread</span><span class="comment"> * control structures and schedules the two protothreads. The main</span><span class="comment"> * function returns when the protothread the runs the code lock exits.</span><span class="comment"> */</span><span class="keywordtype">int</span>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -