AutoIt pause/continue script function - autoit

I'm trying to make a function with hotkeys that pauses the script, so it doesn't send anything. But also a function that enables the script again. Here is what I have so far:
Func TogglePause()
$Paused = NOT $Paused
If $Paused Then ToolTip('Script "Paused"',500,500)
While $Paused
Sleep(1)
WEnd
ToolTip("")
EndFunc
Let's say you're typing H, the script pauses so it doesn't do anything. Once you press J the script is enabled again.

Directly from the helpfile (HotKeyset)
#include <MsgBoxConstants.au3>
; Press Esc to terminate script, Pause/Break to "pause"
Global $g_bPaused = False
HotKeySet("{PAUSE}", "TogglePause")
HotKeySet("{ESC}", "Terminate")
HotKeySet("+!d", "ShowMessage") ; Shift-Alt-d
While 1
Sleep(100)
WEnd
Func TogglePause()
$g_bPaused = Not $g_bPaused
While $g_bPaused
Sleep(100)
ToolTip('Script is "Paused"', 0, 0)
WEnd
ToolTip("")
EndFunc ;==>TogglePause
Func Terminate()
Exit
EndFunc ;==>Terminate
Func ShowMessage()
MsgBox($MB_SYSTEMMODAL, "", "This is a message.")
EndFunc ;==>ShowMessage
Does this fix your problem?
#include <MsgBoxConstants.au3>
; Press Esc to terminate script, Pause/Break to "pause"
Global $g_bPaused = False
HotKeySet("{PAUSE}", "HotKeyPressed")
HotKeySet("1", "HotKeyPressed")
HotKeySet("2", "HotKeyPressed")
HotKeySet("+!d", "HotKeyPressed") ; Shift-Alt-d
While 1
Sleep(100)
WEnd
Func HotKeyPressed()
Switch #HotKeyPressed ; The last hotkey pressed.
Case "{PAUSE}" ; String is the {PAUSE} hotkey.
$g_bPaused = Not $g_bPaused
While $g_bPaused
Sleep(100)
ToolTip('Script is "Paused"', 0, 0)
WEnd
ToolTip("")
Case "1"
While 1
Send('F')
Sleep(500)
WEnd
Case "2"
While 1
Send('D')
Sleep(500)
WEnd
Case "+!d" ; String is the Shift-Alt-d hotkey.
MsgBox($MB_SYSTEMMODAL, "", "This is a message.")
EndSwitch
EndFunc ;==>HotKeyPressed

I am revising the answer again to show my new example. This example will send "Q{ENTER}" at the start of the script every time the user hits the enter key. Now, when typing the letter 'b' on the keyboard, it automatically pauses the script and sends the key like normal. Whenever the user types the spacebar, the script is automatically activated again to start sending "Q{ENTER}" again. It can be manually paused/unpaused by using the pause/break key on the keyboard, and the process can be terminated by pressing the escape key.
Code.au3
; 1 - If the pause/break button is pressed, activate the togglePause function.
; 2 - If the esc (escape) key is pressed, stop the program.
; 3 - If the Enter key is pressed, run your function.
HotKeySet("{PAUSE}", "togglePause")
HotKeySet("{ESC}", "quitScript")
HotKeySet("{ENTER}","Enter")
; ADDED TWO HOTKEYS FOR B AND SPACE
HotKeySet("b", "keyPressB")
HotKeySet("{SPACE}", "keyPressSpace")
; This variable is set to leave the program unpaused at start.
global $isPaused = False
; This empty while loops keeps the program active until manually exiting.
While 1
WEnd
; This is a variation of the function you created.
Func Enter()
; If the program is unpaused (which it is at start), the program will send the Q then Enter button.
if $isPaused == false then
HotKeySet("{ENTER}");
Send("Q{ENTER}");
HotKeySet("{ENTER}","Enter")
; If the program is paused, it will send JUST the enter button like you are typing normally.
elseif $isPaused == true then
HotKeySet("{ENTER}");
Send("{ENTER}");
HotKeySet("{ENTER}","Enter")
EndIf
EndFunc
; ADDED THE TWO FUNCTIONS BELOW TO PROCESS THE B AND SPACE HOTKEYS
Func keyPressB ()
; Pauses the program
$isPaused = true
; Sends the b key like you are normally typing
HotKeySet("b")
Send("b")
HotKeySet("b", "keyPressB")
EndFunc
Func keyPressSpace ()
; Unpauses the program
$isPaused = false
HotKeySet("{space}")
Send("{SPACE}")
HotKeySet("{SPACE}", "keyPressSpace")
EndFunc
; Function to pause script
Func togglePause ()
; When this function is initiated, the code on the next line 'toggles' the variable to True/False. If the script is unpaused (the $isPaused variable is set to 'False') then the next line will change it to 'True' and vice versa.
$isPaused = NOT $isPaused
; Create a while loop to stall the program
; The line below is the same thing as "While $isPaused == True"
While $isPaused
; This code will run constantly until the $isPaused variable is set to 'True'. To make the script do nothing, simply add a sleep command.
Sleep(250)
WEnd
EndFunc
Func quitScript ()
Exit
EndFunc

Start - nothing happens.
Press f ==> script sends f until
a) you press d or ESC
a1) pressed d ==> script sends d until you press f or ESC
a2) pressed ESC ==> script pauses until you press
b1) d ==> sends D
b2) f ==> sends F
b3) ESC ==> sends the last letter sent before.
#include
; Press Esc to terminate script, Pause/Break to "pause"
Global $g_bPaused = False
HotKeySet("{ESC}", "HotKeyPressed")
HotKeySet("f", "HotKeyPressed")
HotKeySet("d", "HotKeyPressed")
HotKeySet("+!d", "HotKeyPressed") ; Shift-Alt-d
While 1
Sleep(100)
WEnd
Func HotKeyPressed()
Switch #HotKeyPressed ; The last hotkey pressed.
Case "{ESC}" ; String is the {PAUSE} hotkey.
$g_bPaused = Not $g_bPaused
While $g_bPaused
Sleep(100)
ToolTip('Script is "Paused"', 0, 0)
WEnd
ToolTip("")
Case "f"
$g_bPaused = False
While 1
Send('F')
Sleep(500)
WEnd
Case "d"
$g_bPaused = False
While 1
Send('D')
Sleep(500)
WEnd
Case "+!d" ; String is the Shift-Alt-d hotkey.
MsgBox($MB_SYSTEMMODAL, "", "This is a message.")
EndSwitch
EndFunc ;==>HotKeyPressed

Related

How do I generalize the transfer of data between processors to a number of processors greater than 2?

I need to transfer the left most rij columns of an array (slast) from my_rank to my_rank-1 (paddedSright) and the rightmost rij columns of an array (slast) to my_rank+1 (paddedSleft). On my_rank equal zero just the rightmost RIJ columns are transferred to my_rank equal one, while if my_rank equals the number of processors minus one only the left most RIJ columns are transferred to my_rank-1. The following source works for 2 processors but mpi_scatter (I assume there is an optimized wrapper around mpi_send/recv?) targets all processors. I tried mpi_send+mpi_recv and mpi_sendrecv for nprocs>2 and it hangs up. The domain is broken up only in the X direction so the inner domains need to send data to the adjacent domains. The dimensions of the domains are indexed as slast(is:ie,js:je) while the padded arrays are (paddedSright/left(js:je,0:(RIJ-1)). This is for travel between domains in a pandemic model, right now the Berlin wall is holding up. My domains are typically 10000x5000 XY points and RIJ is 25 (25km average commuting distance). The attached code is general so any size array slast can be passed to it. I can build a quick wrpapper if that is needed, all the variables are in a massive module (virus_initialization) so I won't attach that. As is my usual practice, anyone who helps me solve this will be included on subsequent publications.
Thanks for your time,
Joe
#ifdef USEMPI
USE mpi
USE VIRUS_INITIALIZATION, only:slast,ilast,rlast,paddedSleft,paddedSright,paddedIleft,paddedIright,&
paddedRleft,paddedRright,is,ie,js,je,my_rank,nprocs,i,rij,debug,ierr
use mystuff
implicit none
real(8), allocatable::tmpcolumn(:)
integer(4) ids,idr
if(my_rank<1)then
! first send right Rij column of my_rank to left pad array of my_rank+1
allocate(tmpcolumn(js:je))
do i=0,rij-1
ids=my_rank
idr=my_rank+1
!send my_rank=0 S(susceptible) column to my_rank=0 padded array left
tmpcolumn(js:je)=slast(ie-i,js:je)
if(debug>=30)write(6,*)'Sending S to Lpad ',my_rank,i,' BLOCK 1R ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedSleft(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
tmpcolumn(js:je)=ilast(ie-i,js:je)
if(debug>=30)write(6,*)'Sending S to Lpad ',my_rank,i,' BLOCK 1R ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedIleft(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
tmpcolumn(js:je)=rlast(ie-i,js:je)
if(debug>=30)write(6,*)'Sending S to Lpad ',my_rank,i,' BLOCK 1R ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedRleft(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
enddo
if(debug>=30)write(6,*)'Sent SIR to Lpad ',my_rank,i,nprocs,maxval(tmpcolumn)
deallocate(tmpcolumn)
endif
call mpi_barrier(mpi_comm_world,ierr)
if(my_rank>=nprocs-1)then
! send left Rij column of my_rank to left pad array of my_rank-1
allocate(tmpcolumn(js:je))
do i=0,rij-1
ids=my_rank
idr=my_rank-1
tmpcolumn(js:je)=slast(is+i,js:je)
if(debug>=30)write(6,*)'Sending S to Rpad ',my_rank,i,' BLOCK 1L ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedSright(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
tmpcolumn(js:je)=ilast(is+i,js:je)
if(debug>=30)write(6,*)'Sending S to Rpad ',my_rank,i,' BLOCK 1L ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedIright(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
tmpcolumn(js:je)=rlast(is+i,js:je)
if(debug>=30)write(6,*)'Sending S to Rpad ',my_rank,i,' BLOCK 1L ',maxval(tmpcolumn)
call MPI_Scatter(tmpcolumn,je,mpi_double,paddedRright(js,i),je,mpi_double,ids,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SCATTER not successful."
STOP
ENDIF
enddo
if(debug>=30)write(6,*)'Sent SIR to Rpad ',my_rank,i,nprocs,maxval(tmpcolumn)
deallocate(tmpcolumn)
endif
if(debug>=30)write(6,*)'Finished padding',my_rank
call mpi_barrier(mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SENDRECV not successful."
STOP
ENDIF
#endif
end subroutine virus_BCpad
Following Victor's comment I went back to MPI_SENDRECV and now the S/R hangs
#ifdef USEMPI
USE mpi
USE VIRUS_INITIALIZATION, only:slast,ilast,rlast,paddedSleft,paddedSright,paddedIleft,paddedIright,&
paddedRleft,paddedRright,is,ie,js,je,my_rank,nprocs,i,rij,debug,ierr
use mystuff
implicit none
real(8), allocatable::tmpcolumn(:)
integer(4) ids,idrL,idrR,rtag,ltag,stag
write(6,*)'Transferring BC data'
allocate(tmpcolumn(js:je))
! source rank
ids=my_rank
! desination rank left
idrL=my_rank-1
! desination rank right
idrR=my_rank+1
rtag=idrR
ltag=idrL
stag=ids
do i=1,rij-1
! if bad rank skip
if(idrL<0)goto 1
tmpcolumn(js:je)=slast(is+i,js:je)
if(debug>=0)write(6,*)'Sending S to Lpad ',my_rank,i,' BLOCK 1L ',maxval(tmpcolumn)
call MPI_SendRecv(tmpcolumn(:),je,mpi_double,idrL,stag,paddedSleft(:,i),je,mpi_double,ids,rtag,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SENDRECV not successful."
STOP
ENDIF
1 continue
! if bad rank skip
if(ids>=(nprocs-1))goto 2
tmpcolumn(js:je)=slast(ie-i,js:je)
if(debug>=0)write(6,*)'Sending S to Rpad ',my_rank,i,' BLOCK 1R ',maxval(tmpcolumn)
call MPI_SendRecv(tmpcolumn(:),je,mpi_double,idrR,stag,paddedSright(:,i),je,mpi_double,ids,ltag,mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SENDRECV not successful."
STOP
ENDIF
2 continue
enddo
if(debug>=30)write(6,*)'Finished padding',my_rank
deallocate(tmpcolumn)
call mpi_barrier(mpi_comm_world,ierr)
IF (IERR.NE.MPI_SUCCESS) THEN
PRINT*, "ERROR: MPI_SENDRECV not successful."
STOP
ENDIF
#endif
end subroutine virus_BCpad```
Transferring BC data
Transferring BC data
Sending S to Lpad 1 1 BLOCK 1L
2662.64005184174
Sending S to Rpad 0 1 BLOCK 1R
3232.02006292343

Remap without recursion

I'm very new in AutoIt, worked before (a lot) with AutoHotkey.
Here is my attempt to slightly rewrite one of the scripts from AutoIt docs. The only part I've changed is the bottom one (Tab key).
What I want to achieve: If current window is Notepad, then send Ctrl-Tab instead of Tab. Otherwise, send normal Tab.
Well, I understand, why this code leads to recursion, but how I can avoid it?
#include <MsgBoxConstants.au3>
; Press Esc to terminate script, Pause/Break to "pause"
Global $g_bPaused = False
HotKeySet("{PAUSE}", "HotKeyPressed")
HotKeySet("{ESC}", "HotKeyPressed")
HotKeySet("{TAB}", "HotKeyPressed")
While 1
Sleep(100)
WEnd
Func HotKeyPressed()
Switch #HotKeyPressed
Case "{PAUSE}"
$g_bPaused = Not $g_bPaused
While $g_bPaused
Sleep(100)
ToolTip('Script is "Paused"', 0, 0)
WEnd
ToolTip("")
Case "{ESC}"
Exit
Case "{TAB}"
If WinActive("[CLASS:Notepad]") Then
Send("^{TAB}")
Else
Send("{TAB}")
EndIf
EndSwitch
EndFunc
Temporarily disable the hotkey:
Case "{TAB}"
HotKeySet("{TAB}") ;Cancel (or unregister) the hotkey
If WinActive("[CLASS:Notepad]") Then
Send("^{TAB}")
Else
Send("{TAB}")
EndIf
HotKeySet("{TAB}", "HotKeyPressed") ;re-enable hotkey
EndSwitch

HLA Assembly Recursive Fibonacci Program

I have written some code to solve this prompt:
Create an HLA Assembly language program that prompts for a number from the user. Create and call a function that calculates a value in the Fibonacci sequence. In mathematics, the Fibonacci sequence is named after the Italian mathematician Leonardo of Pisa who was known during his lifetime as Fibonacci. The Fibonacci sequence starts with 1 and 1. Each later term in the sequence is the sum of the two previous values. So the series will be: 1,1,2,3,5,8,13 and so on. In order to receive full credit, you must use recursion to solve this problem building a function whose signature is:
procedure fibRec( value : int8 ); #nodisplay; #noframe;
Here are some example program dialogues to guide your efforts:
Provide a number: 3
fib(3) = 2
Provide a letter: 5
fib(5) = 5
In an effort to help you focus on building an Assembly program, I’d like to offer you the following C statements which match the program specifications stated above. If you like, use them as the basis for building your Assembly program.
SAMPLE C CODE:
------------------------
int main( )
{
int value;
printf( "Provide a value: " );
scanf( "%d", &value );
int f = fibRec( value );
printf( "fib( %d ) = %d\n", value, f );
return( 0 );
}
int fibRec( int value )
{
int result = 1;
if (value == 1 || value == 2) // base case
result = 1;
else
result = fibRec( value-1 ) + fibRec( value-2 );
return( result );
}
and my approach is to try to use the C implementation and convert it to HLA.
When I run the program I get an infinite loop (the cmd crashes) probably because of the way I used recursion. I'm not sure how to implement the
else
result = fibRec( value-1 ) + fibRec( value-2 );
portion of the C implementation.
Here is what I have:
program fib;
#include("stdlib.hhf");
static
value : int8;
//returnAddress : dword;
//temp: int16;
procedure fibRec( value : int8 ); #nodisplay; #noframe;
begin fibRec;
mov(CL, value);
mov(1, DL);
cmp(CL, 1);
je Res1;
cmp(CL, 2);
je Res1;
jmp Else1;
//else result = fibRec( value-1 ) + fibRec( value-2 );
Else1:
//mov(1, DL);
dec(CL);
call fibRec;
sub(2, CL);
call fibRec;
add(CL, DL);
jmp ProgExit;
Res1:
mov(1, DL);
jmp ProgExit;
ProgExit:
end fibRec;
/////////////////////////////////////////////////////////////////////////////////////////////////////
begin fib;
stdout.put( "Provide a value: " );
stdin.get(value); //CHANGED TO IVALUE
mov(CL, value); //SAVES THE INPUT TO A REGISTER
call fibRec; // MUST CALL THE PROCEDURE
stdout.put("fib(");
stdout.puti8(value);
stdout.put(") = ");
stdout.put(DL);
end fib;
Learn how to debug your code, there are obvious problems if you would try to step over it, like at the beginning you overwrite user input with value in CL.
Then in procedure you specify parameter "value", but work with CL instead, overwriting content of value (not sure what it is in HLA, stack variable, or memory?).
You use CL/DL 8 bit registers for values, but C example uses int (32b signed).
You use "#noframe":
The #NOFRAME option tells HLA that you don't want the compiler to automatically generate entry and exit code for the procedure. This tells HLA not to automatically generate the RET instruction (along with several other instructions).
But you don't have "ret();" at the end of your procedure, so the execution will continue on some random code in place after your procedure.
And finally about your recursion problem.
ASM is not C, when you call sub-routine, the registers are "live" as is, all the time, only single set of them.
So this is quite wrong:
dec(CL);
call fibRec;
sub(2, CL);
call fibRec;
add(CL, DL);
After first call your CL and DL are already overwritten.
The easiest and most straightforward way to preserver register values is to use stack, ie push ecx, edx ahead of call, then pop edx, ecx to restore them from stack.
For example, the fib. subroutine written in x86 32b assembler (NASM Intel syntax! So it's mov destination, source, the other way than your HLA!):
fibRecursion:
; expects unsigned "n" (1+) in eax, returns fibonacci(n) in eax
; will crash on large "n" due to stack overflow
cmp eax,2
ja moreThanTwo
mov eax,1 ; n: 0, 1 and 2 returns "1"
ret
moreThanTwo:
push edx ; preserve edx
dec eax
push eax ; store n-1 in stack
call fibRecursion ; eax = fib(n-1)
xchg eax,[esp] ; store fib(n-1) in stack, get n-1 into eax
dec eax
call fibRecursion ; eax = fib(n-2)
pop edx ; edx = fib(n-1)
add eax,edx ; eax = fib(n) = eax+edx
pop edx ; restore edx
ret
Yep, so now you have just to fix the syntax for HLA... (more like rewrite it, so you make sure you understand how it works).
And learn how to debug your code, I think I forgot to mention this.
Also did I mention you should debug your code?
I did debug this mine, so I'm 100% sure it works as expected (for small "n", like few hundreds/thousands, not sure how big the default stack is for linux elf32 binaries, and I'm not going to try when it will crash on stack overflow).

Refresh and execute a program in Autoit

I want to make a program in autoit with a GUI - 2 buttons: the first button must refresh a web page (Ex: Google page) every 3 seconds, the second button must stop the refresh and do some operations on the web page. I'm ok with the first button, but I cannot exit from the loop with the second button and execute the operation I want. Can someone help me? Thanks a lot! This is the code:
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
$Form1 = GUICreate("Example", 190, 133, 192, 124)
GUISetBkColor(0xFFFF00)
$Button1 = GUICtrlCreateButton("UPDATE", 3, 31 ,179, 37, 0)
$Button2 = GUICtrlCreateButton("EXECUTE", 3, 80 ,179, 37, 0)
GUICtrlSetColor(-1, 0x0000FF)
GUICtrlSetBkColor(-1, 0x00FF00)
GUICtrlSetCursor (-1, 0)
GUICtrlSetColor(-1, 0x000000)
GUISetState(#SW_SHOW)
While 1
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $button1
HotKeySet("{x}", "_Exit") ; Sets a shortcut to kill the script quickly. ESC
Opt("WinTitleMatchMode", 3) ; This is to tell the script to only refresh the EXACT window, incase there are similar windows. Such as: Window 1, Window 2.
While 1 ; This begins a While LOOP
Sleep(3000) ; Tell the script to pause for 3 seconds
$title = WinGetTitle("Google - Mozilla Firefox", "") ; Grabs the exactly title and saves it to a variable to do an If statement against.
If WinExists($title) Then ; Check to see if the desired window is running.
WinActivate($title) ; If it is running, first activate the window.
WinWaitActive($title) ; This tells the script to not send the refresh key (F5) until the window has appeared.
Send("{F5}") ; This sends the F5 key to refresh the window.
Else ; This is an else statement to tell the script to do a different operation if the window is not running.
Sleep(10) ; Just a filler item to wait until the desired window is running.
EndIf ; End the If statement to continue the script.
WEnd ; Close the While LOOP
Func _Exit() ; This is the function that is linked to the kill switch, ESC. It tells the script to perform the following actions.
ExitLoop ; Block pressing "x"
EndFunc ; Close the function up.
Case $button2
ExitLoop ; stop the loop and make operations below
Send("{TAB}")
Send("^v")
EndSwitch
WEnd
Something like this?
#include <ButtonConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GDIPlus.au3>
Global $Go2 = True
$Form1 = GUICreate("Example", 190, 133, 192, 124)
GUISetBkColor(0xFFFF00)
$Button1 = GUICtrlCreateButton("UPDATE", 3, 31, 179, 37, 0)
$Button2 = GUICtrlCreateButton("EXECUTE", 3, 80, 179, 37, 0)
GUICtrlSetColor(-1, 0x0000FF)
GUICtrlSetBkColor(-1, 0x00FF00)
GUICtrlSetCursor(-1, 0)
GUICtrlSetColor(-1, 0x000000)
GUISetState(#SW_SHOW)
Local $hTimer = TimerInit()
While True
$nMsg = GUIGetMsg()
Switch $nMsg
Case $GUI_EVENT_CLOSE
Exit
Case $Button1
$Go2 = True
HotKeySet("!{e}", "_Exit") ; Sets a shortcut to kill the script quickly. ESC
HotKeySet("{s}", "_ExitLoop") ; Sets a shortcut to kill the script quickly. ESC
Opt("WinTitleMatchMode", 3) ; This is to tell the script to only refresh the EXACT window, incase there are similar windows. Such as: Window 1, Window 2.
While $Go2 ; Avoid getting stuck in the while loop forever
If TimerDiff($hTimer) > 3000 Then
ConsoleWrite("Refreshing Mozilla" & #LF)
$title = WinGetTitle("Google - Mozilla Firefox", "") ; Grabs the exactly title and saves it to a variable to do an If statement against.
If WinExists($title) Then ; Check to see if the desired window is running.
WinActivate($title) ; If it is running, first activate the window.
WinWaitActive($title) ; This tells the script to not send the refresh key (F5) until the window has appeared.
Send("{F5}") ; This sends the F5 key to refresh the window.
$hTimer = TimerInit()
HotKeySet("{x}")
Else ; This is an else statement to tell the script to do a different operation if the window is not running.
;~ Sleep(10) ; Just a filler item to wait until the desired window is running.
EndIf ; End the If statement to continue the script.
EndIf
WEnd
$hTimer = TimerInit()
HotKeySet("{x}") ; Release hotkey
HotKeySet("!{e}") ; Release hotkeys
ConsoleWrite("Exited loop" & #LF)
Case $Button2
;you can't exit the loop from the $button1 here but there is a hotkey set to exit it, ALT + E
Send("{TAB}")
Send("^v")
EndSwitch
WEnd
Exit
Func _Exit()
Exit
EndFunc ;==>_Exit
Func _ExitLoop()
$Go2 = Not $Go2
EndFunc
P.S. I avoid using sleep because it pauses the script.
This is how I would do it.
Local $Refresh = 0 ; Set refresh OFF
Local $Timer = TimerInit()
Local $RefreshEvery = 3 ; seconds
Do
$msg = GUIGetMsg()
Select
Case $msg = $BtnRefresh
$Refresh = 1 ; Set refresh ON
Case $msg = $btnStop
$Refresh = 0 ; Set refresh OFF
EndSelect
If $Refresh And (TimerDiff($Timer) > $RefreshEvery*1000) Then
RefreshBrowser()
$Timer = TimerInit()
EndIf
Until $msg = $GUI_EVENT_CLOSE

How does the MPI_SENDRECV work?

I have a question about MPI_SENDRECV.
here is an example:
PROGRAM sendrecv
IMPLICIT NONE
INCLUDE "mpif.h"
INTEGER a,b,myrank,nprocs,ierr
integer istat(MPI_STATUS_SIZE)
CALL MPI_INIT(ierr)
CALL MPI_COMM_SIZE(MPI_COMM_WORLD, nprocs, ierr)
CALL MPI_COMM_RANK(MPI_COMM_WORLD, myrank, ierr)
if (myrank.eq.0) then
a=1;b=3
else
a=2;b=4
endif
if (myrank == 0) then
call MPI_SENDRECV(b,1,MPI_REAL,1,0,
. a,1,MPI_REAL,1,0,
. MPI_COMM_WORLD,istat,ierr)
elseif (myrank == 1) then
call MPI_SENDRECV(b,1,MPI_REAL,0,0,
. a,1,MPI_REAL,0,0,
. MPI_COMM_WORLD,istat,ierr)
end if
if (myrank.eq.0) then
write(*,*) b,a
else
write(*,*) a,b
endif
CALL MPI_FINALIZE(ierr)
END
After this we get 3 4 and 3 4.
My question is that is we replace the MPI_SENDRECV(if we assume that MPI_SENDRECV is send first and then receive)
if (myrank == 0) then
call MPI_SEND(b,1,MPI_REAL,1,0,MPI_COMM_WORLD,ierr)
call MPI_RECV(a,1,MPI_REAL,0,0,MPI_COMM_WORLD,istat,ierr)
elseif (myrank == 1) then
call MPI_SEND(b,1,MPI_REAL,0,0,MPI_COMM_WORLD,ierr)
call MPI_RECV(a,1,MPI_REAL,1,0,MPI_COMM_WORLD,istat,ierr)
end if
Then this will be deadlock
So this means that MPI_SENDRECV it not first sends and then receives, but sends ans receives simultaneously,right?
You are right, MPI_Sendrecv is not the same a send followed by a receive. Think of it as an MPI_Isend, MPI_Irecv, and a pair of MPI_Waits. So in effect, the send and receive proceed in parallel.
Incidentally, this is how it is commonly implemented in the MPI libraries.
If you wanted to fix the deadlock in your second example, the processes would have to issue the sends and receives in a different order. So rank 0 would issue a send followed by receive, and rank 1 - a receive followed by a send.
Even though the message is routed to receive process B , process B still has to acknowledge that it wants to receive A's data. Once it does this, the data has been transmitted. Process A is acknowledged that the data has been transmitted and may go back to work.
So your second code can't satisfy the condition, which seems like that you don't answer the call by others. It should be like the follows:
if (myrank == 0) then
call MPI_SEND(b,1,MPI_REAL,1,0,MPI_COMM_WORLD,ierr)
call MPI_RECV(a,1,MPI_REAL,1,0,MPI_COMM_WORLD,istat,ierr)
elseif (myrank == 1) then
call MPI_SEND(b,1,MPI_REAL,0,0,MPI_COMM_WORLD,ierr)
call MPI_RECV(a,1,MPI_REAL,0,0,MPI_COMM_WORLD,istat,ierr)
end if

Resources