| |
| Components: System Level: Miscellaneous |
| Name: TMonitor |
Date: 3/10/04 7:06:00 PM |
Environment: Delphi 6.0, Delphi 5.0, Delphi 7.0 |
Download |
| Type: Freeware with Source |
Size: |
Price: Source: |
Online Registration: Link Not Available |
Description: Synchronization monitor:
Monitors are high-level synchronization objects. I started mastering synchronization programming in Java. Java is a high-level language that has only one mechanism of synchronization - monitors. These objects are integrated into the language as opposed to C++ and Delphi, which use objects provided by OS.
I was amazed by the fact that monitors are absent in Delphi and decided to implement my own. The lack of the monitors is compensated by the abundance of other (low-level) synchronization objects, e.g. mutex, critical sections, semaphores, events. Do you know when to use a critical section in place of mutex? In addition, Windows supports messages for inter-thread communication. Particularly, messages are used in COM and Delphi(do you remember Synchronized method of TThread object?) to invoke a method of an object that is living in an apartment of another thread. But what gonna you do if the thread you want to talk with does not want to have a message-loop?
There is one more surprise about monitors in Delphi. Reliable inter-thread communication (not message-driven) is not possible without SignalAndWait function that is present in Windows but is not declared in Delphi5. It is funny but all the low level synchronization objects I've listed (mutex, etc.) cannot be used to implement classical produced-consumer paradigm without this function. This paradigm imposes that consumer(s) are waiting until producer(s) has(ve) submitted something for it(them). A consumer checks for a flag of readiness and then starts waiting for data_ready event. A producer can submits data to consumer, sets the data_ready flag and pulses the event. Producer can do all these operations right after consumer checks for the ready flag and enters the waiting state. In this case, the consumer will be waiting forever, because producer is not going to repeat once again. To avoid the situation, there should be only one active thread in the protected section of code (monitor).
As opposed to critical sections and mutexes, where only one thread can enter the object, there can be several threads inside a monitor; however, only one of them is active, all the others are whether waiting or waking up from the waiting state (trying to re-acquire the monitor).
The problem of producer/consumer demo is resolved using the following scenario when using synchronisation monitors. Consumers enter a monitor one-by-one, check that data is not still ready and start waiting allowing for other threads (producers and consumers) enter the monitor. When a producer enters the monitor it checks-in data for the waiting consumers and notifies them. After notification, consumers start waking up one after another, check whether and which data are ready, check the data out and do their job.
For more information about synchronization with monitors look
The differences with Java language are quite obvious - monitors are not a part of the language.
the constriction
synchronize (lock) {
}
is replaced with Lock.Acquire() and Lock.Release(). Here is an example:
// declaration
var Lock: TMonitor
Lock := TMonitor.Create();
//usage
Lock.Acquire();
while (data_not_available) do
Lock.Wait();
// check-out the available data
// ...
// prepare data for another thread that may be waiting for it
Lock.Notify(); // wake up a waiting thread
Lock.Release();
As a result, the compiler cannot check that monitors are used properly. Extensive error-checking is missing as well for the reason that I'm not even sure that I have implemented the object properly. The demo programs I've created using TMonitor operates well. Unfortunately, due to strange artifacts, when starting programs using the TMonitor from Delphi5.0 IDE program may stall (I did not experimented with other IDEs).
Demos:
The work of synchronization monitors is demonstrated by file copying programs. The first thread reads a block from file, submits the block to writer thread which writes the block into destination file. Two threads are required to get a benefit from concurrency when source and destination are located on different disks.
The reader and writer act like producer and consumer in the first program demonstrating a classical producer-consumer relationship. In this program, producer instantiates blocks, fills them with data and passes to writer using synchronization monitor.
However, there is no need for the reader to create the buffers each time and for the consumer to free the block after it finishes with the block. The reader and writer may just own one block and exchange their blocks with each other after each file-access iteration. This functionality of bidirectional data exchange between two threads is demonstrated by the second demo.
|
Additional Information:
- Total downloads between 3/14/04 and 7/6/08: 1281
|
| Author: valentin |
No Homepage Specified |
|
|
|
|
|
| Hits/month |
2,500,000+ |
Downloads (Since May 2000) |
7,393,709 |
| Total Files |
6,023 |
| Forum msgs |
7,670 |
| Articles/FAQs |
70+/900+ |
Top Selling Software at Amazon
|