Windows Programming-synchronization of threads and kernel objects-event kernel objects

Source: Internet
Author: User


Among all kernel objects, event kernel objects are the most basic objects. They containUsage count(Like all kernel objects), one is used to indicate that the event isAuto resetThe event is stillManual resetEventBoolean Value, And the other is used to indicate that the event is inNotified statusOrStatus not notifiedOfBoolean Value.

The event notifies you that an operation has been completed. There are two different types of event objects. One isManual reset event, The other isEvents automatically reset.

When a manually reset event is notified, all threads waiting for the event change to schedulable threads.

When an automatically reset event is notified, only one thread in the thread waiting for the event changes to a schedulable thread.

When one thread executes the initialization operation and notifies another thread to execute the remaining operation, the event is used most. The event is initialized to the state of not notified. After the thread completes its initialization, it sets the event to the notified State. At this time, another thread waiting for the event finds that the event has been notified, so it becomes a schedulable thread. The second thread knows that the first thread has completed its operations.

Below isCreateEventFunction used to create event kernel objects:

 

 HANDLE CreateEvent(
PSECURITY_ATTRIBUTES psa,
BOOLfManualReset,
BOOLfInitialState,
PCTSTRpszName);

 

 

FMannualResetThe parameter is a Boolean value that tells the system whether to create a manual reset event (TRUE) or an automatic reset event (FALSE ).

FInitialStateThe parameter specifies whether the event is initialized to the notified status (TRUE) or not notified status (FALSE ). After the system creates an event object, createEvent returns the process-related handle to the event object.

CreateEventReturn the process-related handle to the event object.

Threads in other processes can obtain access to this object by using the same value (named object) passed in the pszName parameter, using inheritance, using the DuplicateHandle function, and so on to call CreateEvent, you can also call OpenEvent to set a name that matches the name set when CreateEvent is called in the pszName parameter:

 

 

 HANDLEOpenEvent(
DWORD fdwAccess,
BOOL fInherit,
PCTSTR pszName
);

 

 

As in all cases, the CloseHandle function should be called when the event kernel object is no longer needed.

If auto-reset events are used here instead of manually reset events, the behavior characteristics of applications are quite different. After the main thread calls SetEvent, the system allows only one auxiliary thread to change to a schedulable state. Likewise, it cannot be guaranteed which thread the system will change to the schedulable state. The remaining two auxiliary threads will continue to wait.

A thread that has changed to a schedulable state has exclusive access to the memory block. Let's re-compile the thread function so that each function calls the SetEvent function before returning (as the WinMain function does ). These thread functions are now in the following form:

 

 DWORD WINAPI WordCount(PVOID pvParam)
{
//Wait until the file's data is in memory.
WaitForSingleObject(g_hEvent, INFINITE);

//Access the memory block.
...
SetEvent(g_hEvent);
return(0);
}

DWORD WINAPI SpellCheck(PVOID pvParam)
{
//Wait until the file's data is in memory.
WaitForSingleObject(g_hEvent, INFINITE);

//Access the memory block.
...
SetEvent(g_hEvent);
return(0);
}

DWORD WINAPI GrammarCheck(PVOID pvParam)
{
//Wait until the file's data is in memory.
WaitForSingleObject(g_hEvent, INFINITE);

//Access the memory block.
...
SetEvent(g_hEvent);
return(0);
}

 

 

When a thread completes its special data transmission, it calls the SetEvent function, which allows the system to make one of the two waiting threads A schedulable thread. Similarly, we do not know which thread the system will choose as the schedulable thread, but this thread will implement its own dedicated transmission of memory blocks. When the thread completes the operation, it will also call the SetEvent function so that the third, the last thread, can pass its own memory block. Note: When an event is automatically reset, if each auxiliary thread accesses the memory block in read/write mode, no problems will occur, these threads are no longer required to regard data as read-only data.

 

BOOLPulseEvent(HANDLE hEvent );

The PulseEvent function changes the event to the notified State, and then immediately changes to the not notified State, just like calling the ResetEvent function immediately after the SetEvent is called. If the PulseEvent function is called on a manually reset event, when the event is triggered, any or all threads waiting for the event will become schedulable threads. If the PulseEvent function is called on an automatic reset event, only one thread waiting for the event changes to a schedulable thread. If no thread is waiting for the event when an event is triggered, the event will not be affected.

The PulseEvent function is not very useful (you can ignore it first ).

 

An example of Sun Xin's note

 

 # Include <windows. h>
# Include <iostream. h>
// First, two threads are implemented to synchronize the two threads. The last time we used mutex objects to synchronize the CreateMutex function between threads, this time we used event objects to synchronize the CreateEvent between threads.
Dword winapi Fun1Proc (LPVOID lpParameter );
Dword winapi Fun2Proc (LPVOID lpParameter );

Int tickets = 100;
HANDLE g_hEvent; // 1. Define an event HANDLE

Int main ()
{
HANDLE hThread1;
HANDLE hThread2;
HThread1 = CreateThread (NULL, 0, Fun1Proc, NULL, 0, NULL );
HThread2 = CreateThread (NULL, 0, Fun2Proc, NULL, 0, NULL );
CloseHandle (hThread1 );
CloseHandle (hThread2 );
// 2. Create an anonymous event object with a manual reset. The first one is to set security,
// The second is the BOOL setting event type (manually reset TRUE to automatically reset FALSE ),
// Initialization (TRUE (notified) FALSE (not notified ). The fourth is to give the event
// Name,
// For example, if a mutex object is specified, only one instance can be created.

// G_hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); // 3. Set to auto reset
G_hEvent = CreateEvent (NULL, FALSE, FALSE, "tickets"); // name this object tickets
If (g_hevent) // determines whether the object exists
{
If (error_already_exists = getlasterror () // when the program detects that the current object is the same as the instance object you opened
// Error_already_exists will be returned. If this information is received, you will
// Open an opened instance
{
Cout <"cannot open an instance! "<Endl;
Return 0; // return directly without executing the program
}

}
Setevent (g_hevent); // 4. A thread can call
Sleep (10000 );

Closehandle (g_hevent );
Return 0;
}


DWORD winapi fun1proc (lpvoid lpparameter) // if you select an event object that is manually duplicated,
// When the event is in a signal state, all threads waiting for the signal can call it,
// This is not acceptable.
// The event object is similar to the mutex object. Who owns and who releases the event object,
// But because of its own characteristics, as long as the object is in a signal state
// All threads can be accessed, so manual conversion is not allowed.
{
While (true)
{
// 5. The thread waits for the event signal and executes it.
Waitforsingleobject (g_hevent, infinite); // wait for the event object. // after the event object is set to automatic conversion, only one thread is running.
// Stop the thread when it runs only once, because when the event object is notified of automatic conversion,
// Only one thread waiting for the event changes to a schedulable thread,
// Here, the thread becomes schedulable, but the waitforsingleobject of the thread
// Obtain the signal and run it down. The system will set the signal again, which is maintained by the system.
// When the thread slews to the thread, it waits until it does not receive a signal, and then plays in the thread execution,
// Then there will be no signal, and thread. 2 will wait until the main thread sleep event arrives,
// Then end the process. We can set the event object as a signal after the thread is executed.
If (tickets> 0)
{
Sleep (1 );
Cout <"Thread1 effectickets:" <tickets -- <endl;
}
Else
{
Break;
}
SetEvent (g_hEvent); // 6. After the thread is running, the side effects of waiting for success will occur. Set the event object to an unnotified signal.
}

Return 0;
}


Dword winapi Fun2Proc (LPVOID lpParameter)
{

While (TRUE)
{
WaitForSingleObject (g_hEvent, INFINITE); // 7. The thread waits for the event signal and waits for the thread to schedule the execution.
If (tickets> 0)
{
Sleep (1 );
Cout <"Thread2 extends tickets:" <tickets -- <endl;
}
Else
{
Break;
}
SetEvent (g_hEvent); // 8. After the thread is running, wait for the side effects to successfully upload the event object
// Set to no notification signal. This solves the problem,
// Be sure to distinguish between manual or automatic conversion.
// Automatically re-create event objects to allow only one thread to access a total of resources,
// It sets the signal to null after the signal is handed over to a thread,
// Other threads cannot access resources when they do not receive a signal,
// But after the thread executes the protected code, we must
// Reset the signal to a signal state.
}
Return 0; // The following shows that only one instance can be created for the named event object.

}

 

 

 

 

FangSH 2011-01-01

 

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.