Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

In Section 5.7.1, we presented a semaphore-based solution to the producerconsumer problem using a bounded buffer. In this project, you will design a programmingsolution tothe

In Section 5.7.1, we presented a semaphore-based solution to the producerconsumer problem using a bounded buffer. In this project, you will design a programmingsolution tothe bounded-buffer problemusing the producer and consumer processes shown in Figures 5.9 and 5.10. The solution presented in Section 5.7.1 uses three semaphores: empty and full, which count the number of empty and full slots in the buffer, and mutex, which is a binary (or mutualexclusion) semaphore that protects the actual insertion or removal of items in the buffer. For this project, you will use standard counting semaphores for emptyandfullandamutexlock,ratherthanabinarysemaphore,torepresent mutex.Theproducerandconsumerrunningasseparatethreadswillmove itemstoandfromabufferthatissynchronizedwiththeempty,full,andmutex structures. You can solve this problem using either Pthreads or the Windows API. #include "buffer.h" /* the buffer */ buffer item buffer[BUFFER int insert item(buffer SIZE]; item item) { /* insert item into buffer return 0 if successful, otherwise return -1 indicating an error condition */ } int remove item(buffer item *item) { /* remove an object from buffer placing it in item return 0 if successful, otherwise return -1 indicating an error condition */ } The Buffer Figure 5.24 Outline of buffer operations. Internally, the buffer will consist of a fixed-size array of type buffer (which will be defined using a typedef). The array of buffer item objects will be manipulated as a circular queue. The definition of buffer item,along with the size of the buffer, can be stored in a header file such as the following: /* buffer.h */ typedef int buffer #define BUFFER item; SIZE 5 The buffer will be manipulated with two functions, insert remove item item() and item(), which are called by the producer and consumer threads, respectively. A skeleton outlining these functions appears in Figure 5.24. The insert item() and remove item() functions will synchronize the producer and consumer using the algorithms outlined in Figures 5.9 and 5.10. The buffer will also require an initialization function that initializes the mutual-exclusion object mutex along with the empty and full semaphores. The main() function will initialize the buffer and create the separate producer and consumer threads. Once it has created the producer and consumer threads, the main() function will sleep for a period of time and, upon awakening, will terminate the application. The main() function will be passed three parameters on the command line: 1. How long to sleep before terminating 2. The number of producer threads 3. The number of consumer threads #include "buffer.h" Programming Projects 255 int main(int argc, char *argv[]) { /* 1. Get command line arguments argv[1],argv[2],argv[3] */ /* 2. Initialize buffer */ /* 3. Create producer thread(s) */ /* 4. Create consumer thread(s) */ /* 5. Sleep */ /* 6. Exit */ } Figure 5.25 Outline of skeleton program. Askeleton for this function appears in Figure 5.25. The Producer and Consumer Threads The producer thread will alternate between sleeping for a random period of time and inserting a random integer into the buffer. Random numbers will be produced using the rand() function, which produces random integers between 0 and RAND MAX. The consumer will also sleep for a random period of time and, upon awakening, will attempt to remove an item from the buffer. Anoutline of the producer and consumer threads appears in Figure 5.26. As noted earlier, you can solve this problem using either Pthreads or the Windows API. In the following sections, we supply more information on each of these choices. Pthreads Thread Creation and Synchronization Creating threads using the Pthreads API is discussed in Section 4.4.1. Coverage of mutex locks and semaphores using Pthreads is provided in Section 5.9.4. Refer to those sections for specific instructions on Pthreads thread creation and synchronization. Windows Section 4.4.2 discusses thread creation using the Windows API. Refer to that section for specific instructions on creating threads. Windows MutexLocks Mutex locks are a type of dispatcher object, as described in Section 5.9.1. The following illustrates how to create a mutex lock using the CreateMutex() function: #include HANDLE Mutex; Mutex = CreateMutex(NULL, FALSE, NULL); #include /* required for rand() */ #include "buffer.h" void *producer(void *param) { buffer item item; while (true) { /* sleep for a random period of time */ sleep(...); /* generate a random number */ item = rand(); if (insert item(item)) fprintf("report error condition"); else printf("producer produced %d ",item); } void *consumer(void *param) { buffer item item; while (true) { /* sleep for a random period of time */ sleep(...); if (remove item(&item)) fprintf("report error condition"); else printf("consumer consumed %d ",item); } Figure 5.26 An outline of the producer and consumer threads. The first parameter refers to a security attribute for the mutex lock. By setting this attribute to NULL, we disallow any children of the process creating this mutex lock to inherit the handle of the lock. The second parameter indicates whetherthecreatorofthemutexlockisthelocksinitialowner.Passing avalue of FALSE indicates that the thread creating the mutex is not the initial owner. (We shall soon see how mutex locks are acquired.) The third parameter allows us to name the mutex. However, because we provide a value of NULL,wedo not name the mutex. If successful, CreateMutex() returns a HANDLE to the mutex lock; otherwise, it returns NULL. In Section 5.9.1, we identified dispatcher objects as being either signaled or nonsignaled. A signaled dispatcher object (such as a mutex lock) is available for ownership. Once it is acquired, it moves to the nonsignaled state. When it is released, it returns to signaled. Mutex locks are acquired by invoking the WaitForSingleObject() function. The function is passed the HANDLE to the lock along with a flag indicating howlongtowait.Thefollowingcodedemonstrateshowthemutexlockcreated above can be acquired: WaitForSingleObject(Mutex, INFINITE); The parameter value INFINITE indicates that we will wait an infinite amount of timefor thelocktobecomeavailable.Othervaluescouldbeusedthatwould allow the calling thread to time out if the lock did not become available within a specified time. If the lock is in a signaled state, WaitForSingleObject() returns immediately, and the lock becomes nonsignaled. A lock is released (moves to the signaled state) by invoking ReleaseMutex()for example, as follows: ReleaseMutex(Mutex); Windows Semaphores Semaphores in the Windows API are dispatcher objects and thus use the same signaling mechanism as mutex locks. Semaphores are created as follows: #include HANDLE Sem; Sem = CreateSemaphore(NULL, 1, 5, NULL); The first and last parameters identify a security attribute and a name for the semaphore,similartowhatwedescribedformutexlocks.Thesecondandthird parameters indicate the initial value and maximum value of the semaphore. In this instance, the initial value of the semaphore is 1, and its maximum value is 5. If successful, CreateSemaphore() returns a HANDLE to the mutex lock; otherwise, it returns NULL. Semaphores are acquired with the same WaitForSingleObject() function as mutex locks. We acquire the semaphore Sem created in this example by using the following statement: WaitForSingleObject(Semaphore, INFINITE); If the value of the semaphore is > 0, the semaphore is in the signaled state and thusis acquired by the calling thread. Otherwise, the calling thread blocks indefinitelyas we are specifying INFINITEuntil the semaphore returns to the signaled state. The equivalent of the signal() operation for Windows semaphores is the ReleaseSemaphore() function. This function is passed three parameters: 1. TheHANDLEofthe semaphore 2. Howmuchtoincrease the value of the semaphore 3. Apointer to the previous value of the semaphore Wecanuse the following statement to increase Sem by 1: ReleaseSemaphore(Sem, 1, NULL); Both ReleaseSemaphore() and ReleaseMutex() return a nonzero value if successful and 0 otherwise.

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Database And Expert Systems Applications 15th International Conference Dexa 2004 Zaragoza Spain August 30 September 3 2004 Proceedings Lncs 3180

Authors: Fernando Galindo ,Makoto Takizawa ,Roland Traunmuller

2004th Edition

3540229361, 978-3540229360

More Books

Students also viewed these Databases questions