How synchronization works
Synchronization involves sharing a single CPU among multiple tasks (or threads) in a way designed to minimize the time required to switch threads. On a thread-enabled server, agents take turns performing their tasks, which saves time and gives the illusion of the tasks occuring at the same time.
This sample agent, Comm1, run at the same time as an identical one named Comm2, illustrates how you can use code locks to synchronize agent execution.
Run concurrently, these agents create a named lock called "Update," then:
- If Comm1 is the first agent to start execution, it gets the lock; the second (Comm2) must wait for Comm1 to release it before starting. Comm1 outputs a message that it has the lock and provides the reference count.
- As soon as Comm1 is done with the lock, it releases it and Comm2 takes it. Comm1 tries to obtain the lock again, but now must wait until Comm2 is done with it. Comm2 outputs a message that it now has the lock and reports the reference count again.
- As soon as Comm2 is done with the lock, it releases it and Comm1 takes it.
The process repeats for the duration of "For loop," in this case, 5 iterations.
'Comm1:
Option Public
' Remove the following line if you do not have a
' resource library defined.
Use "ThreadsLib"
Sub Initialize
Dim lockName As String
Dim lockID As Integer, refcnt As Integer
Dim gotLock As Variant, releaseLock As Variant, _
deleteLock As Variant
On Error Goto syn_error
' Provide some unique name here to distinguish the agents.
ID = "Comm1 tuvwx:5706 "
Msgbox ID & "Started"
lockName = "Update"
On Error Goto syn_error
' Create the lock
lockID = Createlock(uName)
If (lockID <> -1) Then
Msgbox ID & "Created lock: " & lockID
End If
' Put agent to sleep for a second.
' This gives the second agent time to start.
Sleep 1
For x = 1 To 5
' Attempt to get the lock and report the outcome
' as well as the reference count
gotLock = CodeLock(lockID)
If (gotLock) Then
Msgbox ID & " Got lock: " & lockID & " - at: " & _
Now()
refcnt = Codelockcheck(lockID)
Msgbox ID & " Reference count is " & refcnt
' Do some meaningful work here, or just sleep
Sleep 1
Else
Msgbox ID & "Failed to get lock"
End If
' Release the lock so the other agent can get it.
releaseLock = Codeunlock(lockID)
If (releaseLock) Then
Msgbox ID & " Releasing lock: " & lockID & _
" - at: " & Now()
' Sleep here allows the other agents to obtain
' the lock before this agent has a chance to.
Sleep 1
Else
Msgbox ID & "Failed to release lock"
End If
Next
' When we are finished, destroy this agent's reference
' to the lock
deleteLock = Destroylock(lockID)
If (deleteLock ) Then
Msgbox ID & "Destroyed lock " & lockID
Else
Msgbox ID & "Failed to destroy lock"
End If
Msgbox ID & "Done "
Exit Sub
syn_error:
errormsg = " * * Error: " & Err & " - " & Error() & _
" in " & ID & " at " & Erl()
Msgbox errormsg
Resume Next
End Sub
A sample output of Comm1 (with an ID of tuvwx:5706) and Comm2 (with an ID of uvwxy:5742) running concurrently as agents through the Domino® Web server would look something like the following:
Addin: Agent message box: Comm1 tuvwx:5706 Started Addin: Agent message box: Comm1 tuvwx:5706 Created lock: 0 Addin: Agent message box: Comm2 uvwxy:5742 Started Addin: Agent message box: Comm2 uvwxy:5742 Created lock: 0 Addin: Agent message box: Comm1 tuvwx:5706 Got lock: 0 - at: 2/10/99 1:57:06 PM Addin: Agent message box: Comm1 tuvwx:5706 Reference count is 1 Addin: Agent message box: Comm2 uvwxy:5742 Got lock: 0 - at: 2/10/99 1:57:07 PM Addin: Agent message box: Comm2 uvwxy:5742 Reference count is 1 Addin: Agent message box: Comm1 tuvwx:5706 Releasing update_lock: 0 - at: 2/10/99 1:57:07 PM Addin: Agent message box: Comm2 uvwxy:5742 Releasing update_lock: 0 - at: 2/10/99 1:57:08 PM Addin: Agent message box: Comm1 tuvwx:5706 Got lock: 0 - at: 2/10/99 1:57:08 PM Addin: Agent message box: Comm1 tuvwx:5706 Reference count is 1 Addin: Agent message box: Comm2 uvwxy:5742 Got lock: 0 - at: 2/10/99 1:57:09 PM Addin: Agent message box: Comm2 uvwxy:5742 Reference count is 1 Addin: Agent message box: Comm1 tuvwx:5706 Releasing lock: 0 - at: 2/10/99 1:57:09 PM Addin: Agent message box: Comm2 uvwxy:5742 Releasing lock: 0 - at: 2/10/99 1:57:10 PM Addin: Agent message box: Comm1 tuvwx:5706 Got lock: 0 - at: 2/10/99 1:57:10 PM Addin: Agent message box: Comm1 tuvwx:5706 Reference count is 1 Addin: Agent message box: Comm2 uvwxy:5742 Got lock: 0 - at: 2/10/99 1:57:12 PM Addin: Agent message box: Comm2 uvwxy:5742 Reference count is 1 Addin: Agent message box: Comm1 tuvwx:5706 Releasing lock: 0 - at: 2/10/99 1:57:12 PM Addin: Agent message box: Comm2 uvwxy:5742 Releasing lock: 0 - at: 2/10/99 1:57:13 PM Addin: Agent message box: Comm1 tuvwx:5706 Got lock: 0 - at: 2/10/99 1:57:13 PM Addin: Agent message box: Comm1 tuvwx:5706 Reference count is 1 Addin: Agent message box: Comm2 uvwxy:5742 Got lock: 0 - at: 2/10/99 1:57:14 PM Addin: Agent message box: Comm2 uvwxy:5742 Reference count is 1 Addin: Agent message box: Comm1 tuvwx:5706 Releasing lock: 0 - at: 2/10/99 1:57:14 PM Addin: Agent message box: Comm2 uvwxy:5742 Releasing lock: 0 - at: 2/10/99 1:57:15 PM Addin: Agent message box: Comm1 tuvwx:5706 Got lock: 0 - at: 2/10/99 1:57:15 PM Addin: Agent message box: Comm1 tuvwx:5706 Reference count is 1 Addin: Agent message box: Comm2 uvwxy:5742 Got lock: 0 - at: 2/10/99 1:57:16 PM Addin: Agent message box: Comm2 uvwxy:5742 Reference count is 1 Addin: Agent message box: Comm1 tuvwx:5706 Releasing lock: 0 - at: 2/10/99 1:57:16 PM Addin: Agent message box: Comm2 uvwxy:5742 Releasing lock: 0 - at: 2/10/99 1:57:18 PM Addin: Agent message box: Comm1 tuvwx:5706 Destroyed lock 0 Addin: Agent message box: Comm1 tuvwx:5706 Done Addin: Agent message box: Comm2 uvwxy:5742 Destroyed lock 0 Addin: Agent message box: Comm2 uvwxy:5742 Done
These primitives are used only for communication between instances of cooperating LotusScript® agents within a single process. They are designed specifically for asynchronous Web agents.
Supported platforms include Win32, UNIX™ (AIX®).