version 11 (Modified)
Semaphore (semaphore{; tickCount}) Boolean
Parameter | Type | Description | |
semaphore | String | Semaphore to test and set | |
tickCount | Integer | Maximum waiting time | |
Function result | Boolean | Semaphore has been successfully set (FALSE) or | |
Semaphore was already set (TRUE) |
Description
A semaphore is a flag shared among workstations (each user's computer) or among processes on the same workstation. A semaphore simply exists or does not exist. The methods that each user is running can test for the existence of a semaphore. By creating and testing semaphores, methods can communicate between workstations.
The Semaphore function returns TRUE if semaphore exists. If semaphore does not exist, Semaphore creates it and returns FALSE. Only one user at a time can create a semaphore. If Semaphore returns FALSE, it means that the semaphore did not exist, but it also means that the semaphore has been set for the process in which the call has been made.
Semaphore returns FALSE if the semaphore was not set. It also returns FALSE if the semaphore is already set by the same process in which the call has been made. semaphore is limited to 255 characters, including prefixes (<>, $). If you pass a longer string, the semaphore will be tested with the truncated string.
The optional parameter tickCount allows you to specify a waiting time (in ticks) if semaphore is already set. In this case, the function will wait either for the semaphore to be freed or the waiting time to expire before returning True.
There are two types of semaphores in 4D: local semaphores and global semaphores.
A local semaphore is accessible by all processes on the same workstation and only on the workstation. A local semaphore can be created by prefixing the name of the semaphore with a dollar sign ($). You use local semaphores to monitor operations among processes executing on the same workstation. For example, a local semaphore can be used to monitor access to an interprocess array shared by all the processes in your single-user database or on the workstation.
A global semaphore is accessible to all users and all their processes. You use global semaphores to monitor operations among users of a multi-user database.
Global and local semaphores are identical in their logic. The difference resides in their scope.
In 4D Server, global semaphores are shared among all the processes running on all clients. A local semaphore is only shared among the processes running on the client where it has been created.
In 4D, global or local semaphores have the same scope because you are the only user. However, if your database is being used in both setups, make sure to use global or local semaphores depending on what you want to do.
You do not use semaphores to protect record access. This is automatically done by 4D and 4D Server. Use semaphores to prevent several users from performing the same operation at the same time.
Examples
1. In this example, you want to prevent two users from doing a global update of the prices in a Products table. The following method uses semaphores to manage this:
If (Semaphore("UpdatePrices")) ` Try to create the semaphore ALERT("Another user is already updating prices. Retry later.") Else DoUpdatePrices ` Update all the prices CLEAR SEMAPHORE("UpdatePrices")) ` Clear the semaphore End if
2. The following example uses a local semaphore. In a database with several processes, you want to maintain a To Do list. You want to maintain the list in an interprocess array and not in a table. You use a semaphore to prevent simultaneous access. In this situation, you only need to use a local semaphore, because your To Do list is only for your use.
The interprocess array is initialized in the Startup method:
ARRAY TEXT(<>ToDoList;0) ` The To Do list is initially empty
Here is the method used for adding items to the To Do list:
` ADD TO DO LIST project method ` ADD TO DO LIST ( Text ) ` ADD TO DO LIST ( To do list item ) C_TEXT($1) If(Not(Semaphore("$AccessToDoList";300))) ` Wait 5 seconds if the semaphore already exists $vlElem:=Size of array(<>ToDoList)+1 INSERT IN ARAY(<>ToDoList;$vlElem) <>ToDoList{$vlElem}:=$1 CLEAR SEMAPHORE("$AccessToDoList") ` Clear the semaphore End if
You can call the above method from any process.
See Also
CLEAR SEMAPHORE, Test semaphore.