From Xojo Documentation
Used to control access to resources in a multithreaded environment.
|Release||Call Release to give a locked resource back to the Semaphore.
You must call Release when you are finished using a locked resource in order to make it available to other requests.
|Signal||Call Signal to obtain a lock on a resource. Once you are done with the shared resource, the thread should call Release to increment the internal counter.
Every time thread calls Signal, the Semaphore decrements the counter. If the counter is less than zero, it suspends the thread. When you obtain a lock, you can use the resource without fear that another thread will try to use it simultaneously. If the call succeeds, this function returns immediately and you code continues to execute. If the lock is not available, then the thread that called this method will wait until the lock becomes available. When the call returns, you will have the lock, but you may have to wait until the lock becomes available. When you are finished using the resource, call the Release method to give it back to the Semaphore.
|Boolean||This is a more friendly version of the Signal method that gives you a sneak-peek to determine whether there is a lock available.
If there is a lock available, you are granted the lock and TrySignal returns True. When you are finished with the resource, call Release to give it back to the Semaphore. If the lock is not available, you do not wait for it. Instead, TrySignal returns False to let you know. Do not attempt to use the resource after it returns False because you are likely to collide with another thread. If you
The Semaphore has a constructor that takes the initial count of the number of resources the semaphore is protecting as an optional parameter.
|Semaphore||NumResources as Integer||The number of resources the Semaphore is intended to protect. This defaults to 1.
If you need to manage access to a single resource, you can instead use a CriticalSection.
Every time you successfully obtain a lock on the resource, the Semaphore will decrement its internal count of available resources. When there are no more resources, threads that request locks will begin to block and wait for resources. This is why you are allowed to pass the initial count of resources, to give you more control over the behavior of the Semaphore.
The Semaphore class is different from the CriticalSection and Mutex classes in this way: calling Signal in the same thread will cause the counter to decrement. If you call Signal recursively, you will cause the application to hang.
A Semaphore is an object that can be used to coordinate access to a shared resource.
To acquire the ownership of a semaphore, a thread calls the Signal or TrySignal methods. If the Semaphore isn't owned, the thread acquires ownership, otherwise the thread will be forced to wait until the Semaphore is released via the Release method by the owning thread.
The example uses a Pushbutton in a window to spawn some threads. Its Action event code is:
// Make a new thread
Dim newThread as ThreadSpawn
// Be sure to advance our thread id
mNextID = mNextID + 1
// And run the new thread
mSharedResourceManger = manager
mThreadNumber = ID
mSharedResourceManager is a Window1 property of ThreadSpawn and mThreadNumber is an Integer property of ThreadSpawn.
Its Run event handler is:
// We're going to loop forever and ever
// We want to try to access the shared
// resource, so we call it on the Window
// And then go to sleep for some random amount of time
When the window opens, the PushButton is pushed programmatically to create some threads. The window's Open event handler is:
mLock = New Semaphore
// We're going to spawn a few threads
// to start off with
Window1 is derived from Window and has the ChangedSharedResource method:
// We want to make sure that only the right thread gets in here. One at a
//mLock is a Semaphore property of Window1
//mNextID is an Integer property of Window1
// Now that we're here, we can change the resource
//SharedResource and AccessText are StaticTexts in Window1
SharedResource.Text = value
AccessText.Text = Str( id )
// And now that we've done something with the
// resource, we want to release our lock on it