Producer and consumer: C ++

Source: Internet
Author: User

# Include <windows. h>
# Include <fstream. h>
# Include <stdio. h>
# Include <string>
# Include <conio. h>

// Define some constants;

// Maximum number of critical zones allowed by this program;
# Define MAX_BUFFER_NUM 10

// Multiplication factor from seconds to microseconds;
# Define INTE_PER_SEC 1000

// The total number of Production and Consumption threads allowed by this program;
# Define MAX_THREAD_NUM 64

// Define a structure to record the parameters of each thread specified in the test file
Struct ThreadInfo
{
Int serial; // thread serial number
Char entity; // whether it is P or C
Double delay; // thread latency
Int thread_request [max_thread_num]; // thread Request queue
Int n_request; // number of requests
};

// Global variable definition

// Declaration of the Critical Area object, used to manage the mutex access of the buffer zone;
Int buffer_critical [max_buffer_num]; // buffer declaration, used to store the product;
Threadinfo thread_info [max_thread_num]; // an array of thread information;
Handle h_thread [max_thread_num]; // array used to store each thread handle;

HANDLE empty_semaphore; // a semaphore;
HANDLE h_mutex; // A mutex;
HANDLE h_Semaphore [MAX_THREAD_NUM]; // The semaphore that the producer allows the consumer to start consumption;
CRITICAL_SECTION PC_Critical [MAX_BUFFER_NUM];

DWORD n_Thread = 0; // the actual number of threads;
DWORD n_Buffer_or_Critical; // number of actual buffers or critical zones;

// Declaration of production consumption and auxiliary functions
Void Produce (void * p );
Void Consume (void * p );
Bool IfInOtherRequest (int );
Int FindProducePositon ();
Int FindBufferPosition (int );

Int main (int argc, char ** argv)
{
// Declare the required variables;
DWORD wait_for_all;
Ifstream inFile;

If (argc! = 2 ){
Printf ("Usage: % s <File>/n", argv [0]);
Return 1;
}

// Initialize the buffer;
For (int I = 0; I <MAX_BUFFER_NUM; I ++)
Buffer_critical [I] =-1;

// Initialize the Request queue of each thread;
For (Int J = 0; j <max_thread_num; j ++ ){
For (int K = 0; k <max_thread_num; k ++)
Thread_info [J]. thread_request [k] =-1;

Thread_info [J]. n_request = 0;
}

// Initialize the critical section;
For (I = 0; I <max_buffer_num; I ++)
Initializecriticalsection (& pc_critical [I]);

// Open the input file and extract thread information according to the specified format;
Infile. Open (argv [1]);

// Obtain the actual number of buffers from the file, that is, the first row of the test file;
InFile> n_Buffer_or_Critical;
InFile. get (); // read the space in the test file and point the file pointer to the next line;
Printf ("input file:/n ");

// The number of buffers obtained by ECHO;
Printf ("% d/n", (int) n_Buffer_or_Critical );

// Extract information of each thread to the corresponding data structure;
While (inFile ){
InFile> Thread_Info [n_Thread]. serial;
InFile> Thread_Info [n_Thread]. entity;
InFile> Thread_Info [n_Thread]. delay;

Char c;
InFile. get (c );

While (c! = '/N '&&! InFile. eof ()){
InFile> Thread_Info [n_Thread]. thread_request [Thread_Info [n_Thread]. n_request ++];
InFile. get (c );
}

N_Thread ++;
}

// Display the thread information obtained by ECHO to check whether the thread information is correct;
For (j = 0; j <(int) n_Thread; j ++ ){
Int Temp_serial = Thread_Info [j]. serial;
Char Temp_entity = Thread_Info [j]. entity;
Double Temp_delay = Thread_Info [j]. delay;

Printf ("/nthread % 2d % c % f", Temp_serial, Temp_entity, Temp_delay );

Int Temp_request = Thread_Info [j]. n_request;

For (int k = 0; k <Temp_request; k ++)
Printf ("% d", Thread_Info [j]. thread_request [k]);

Cout <endl;
}

Printf ("/n ");

// Create several necessary semaphores During Simulation
Empty_semaphore = CreateSemaphore (NULL, n_Buffer_or_Critical, n_Buffer_or_Critical,
"Semaphore_for_empty ");
H_mutex = CreateMutex (NULL, FALSE, "mutex_for_update ");

// The following cycle uses the thread ID to read and write the product of the corresponding production thread.
// Use the synchronous semaphore name;
For (j = 0; j <(int) n_Thread; j ++ ){
Char lp [] = "semaphore_for_produce _";
Int temp = j;
While (temp ){
Char c = (char) (temp % 10 );
Strcat (lp, & c );
Temp/= 10;
}

H_Semaphore [j + 1] = CreateSemaphore (NULL, 0, n_Thread, lp );
}

// Create producer and consumer threads;
For (I = 0; I <(int) n_Thread; I ++ ){
If (Thread_Info [I]. entity = 'P ')
H_Thread [I] = CreateThread (NULL, 0, (LPTHREAD_START_ROUTINE) (Produce ),
& (Thread_Info [I]), 0, NULL );
Else
H_thread [I] = createthread (null, 0, (lpthread_start_routine) (consume ),
& (Thread_info [I]), 0, null );
}

// The main program waits for the action of each thread to end;
Wait_for_all = waitformultipleobjects (n_thread, h_thread, true,-1 );

Printf ("/n/Nall producer and consumer have finished their work./N ");
Printf ("press any key to quit! /N ");
_ Getch ();
Return 0;
}

// Confirm whether there are still consumption requests for the same product that have not been executed;
Bool ifinotherrequest (INT req)
{
For (INT I = 0; I <n_thread; I ++)
For (Int J = 0; j <thread_info [I]. n_request; j ++)
If (thread_info [I]. thread_request [J] = req)
Return true;

Return false;
}

// Locate the available empty buffer zone for product production;
Int findproduceposition ()
{
Int emptyposition;
For (INT I = 0; I <n_buffer_or_critical; I ++)
If (buffer_critical [I] =-1 ){
Emptyposition = I;

// Use the following special value to indicate that the buffer is being written;
Buffer_critical [I] =-2;
Break;
}
Return emptyposition;
}

// Locate the position of the product to be produced by the current producer;
Int findbufferposition (INT propos)
{
Int temppos;
For (INT I = 0; I <n_buffer_or_critical; I ++)
If (buffer_critical [I] = propos ){
Temppos = I;
Break;
}
Return temppos;
}

// Producer Process
Void produce (void * P)
{
// Local variable Declaration;
DWORD wait_for_semaphore, wait_for_mutex, m_delay;
Int m_serial;

// Obtain the thread information;
M_serial = (threadinfo *) (p)-> serial;
M_delay = (DWORD) (threadinfo *) (p)-> delay * inte_per_sec );

Sleep (m_delay );
// Start request Production
Printf ("producer % 2D sends the produce require./N", m_serial );

// Mutually exclusive access to the next blank critical area that can be used for production to achieve mutually exclusive write and write;
Wait_for_mutex = waitforsingleobject (h_mutex,-1 );

// Confirm that the free buffer zone is available for production, and reduce the number of empty locations by 1; used for synchronization between producers and consumers;
// Wait until the consumer process releases the resource;
Wait_for_semaphore = waitforsingleobject (empty_semaphore,-1 );

Int producepos = findproduceposition ();
Releasemutex (h_mutex );

// After the producer obtains its own null position and marks it, the following write operations can be performed concurrently between producers;
// In the core production step, the program uses the producer ID as the product ID to facilitate consumer identification;
Printf ("producer % 2D begin to produce at position % 2D./N", m_serial, producepos );
Buffer_critical [producepos] = m_serial;
Printf ("producer % 2D Finish producing:/N", m_serial );
Printf ("position [% 2D]: % 3d/n", producepos, buffer_critical [producepos]);

// Enable the buffer written by the producer to be used by multiple consumers for read/write synchronization;
ReleaseSemaphore (h_Semaphore [m_serial], n_Thread, NULL );
}

// Consumer Process
Void Consume (void * p)
{
// Local variable Declaration;
DWORD wait_for_semaphore, m_delay;
Int m_serial, m_requestNum; // the serial number of the consumer and the number of requests;
Int m_thread_request [MAX_THREAD_NUM]; // Request queue of the consumption thread;

// Extract the thread information to the local device;
M_serial = (ThreadInfo *) (p)-> serial;
M_delay = (DWORD) (ThreadInfo *) (p)-> delay * INTE_PER_SEC );
M_requestNum = (ThreadInfo *) (p)-> n_request;

For (int I = 0; I <m_requestNum; I ++)
M_thread_request [I] = (ThreadInfo *) (p)-> thread_request [I];

Sleep (m_delay );

// Consume the required products cyclically
For (I = 0; I <m_requestNum; I ++ ){

// Request to consume the next product
Printf ("Consumer % 2d request to consume % 2d product/n", m_serial, m_thread_request [I]);

// If the corresponding producer does not have production, wait; if production is in progress, the number of consumers allowed is-1; read/write synchronization is realized;
Wait_for_semaphore = WaitForSingleObject (h_Semaphore [m_thread_request [I],-1 );

// Query the number of the product to be placed in the buffer zone
Int BufferPos = FindBufferPosition (m_thread_request [I]);

// Start the consumption Processing of a specific buffer. The read and read operations are mutually exclusive in the buffer;
// After entering the critical section, execute the Consumption Action. After completing this request, notify another consumer that the request has been
// Met; and if the corresponding product is used up, it will be processed accordingly; and the interface for corresponding actions will be provided
// Display; this processing refers to clearing the corresponding buffer and adding a semaphore representing the empty buffer;
EnterCriticalSection (& PC_Critical [BufferPos]);
Printf ("Consumer % 2d begin to consume % 2d product/n", m_serial, m_thread_request [I]);
(ThreadInfo *) (p)-> thread_request [I] =-1;

If (! IfInOtherRequest (m_thread_request [I]) {
Buffer_critical [bufferpos] =-1; //-1 indicates that the buffer zone is empty;
Printf ("Consumer % 2D finish consuming % 2D:/N", m_serial, m_thread_request [I]);
Printf ("position [% 2D]: % 3d/n", bufferpos, buffer_critical [bufferpos]);
Releasesemaphore (empty_semaphore, 1, null );
}
Else {
Printf ("Consumer % 2D finish consuming product % 2D/n", m_serial, m_thread_request [I]);
}

// Exit the critical section
Leavecriticalsection (& pc_critical [bufferpos]);
}
}

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.