Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
SSW_8_11.doc
Скачиваний:
0
Добавлен:
17.02.2020
Размер:
5.22 Mб
Скачать

7.3 The working with semaphore

First of all – create the object of CSemaphore type:

CSemaphore::CSemaphore( LONG lInitialCount = 1, LONG lMaxCount = 1, LPCTSTR pstrName = NULL, LPSECURITY_ATTRIBUTES lpsaAttributes = NULL );

Parameters:

lInitialCount   The initial usage count for the semaphore. Must be greater than or equal to 0, and less than or equal to lMaxCount.

lMaxCount   The maximum usage count for the semaphore. Must be greater than 0.

pstrName   The name of the semaphore. Must be supplied if the semaphore will be accessed across process boundaries. If NULL, the object will be unnamed. If the name matches an existing semaphore, the constructor builds a new CSemaphore object which references the semaphore of that name. If the name matches an existing synchronization object that is not a semaphore, the construction will fail.

lpsaAttributes   Security attributes for the semaphore object.

To use a CSemaphore object, construct the CSemaphore object when it is needed. Specify the name of the semaphore you wish to wait on, and that your application should initially own it. You can then access the semaphore when the constructor returns. Call CSyncObject::Unlock when you are done accessing the controlled resource.

An alternative method for using CSemaphore objects is to add a variable of type CSemaphore as a data member to the class you wish to control. During construction of the controlled object, call the constructor of the CSemaphore data member specifying the initial access count, maximum access count, name of the semaphore (if it will be used across process boundaries), and desired security attributes.

To access resources controlled by CSemaphore objects in this manner, first create a variable of either type CSingleLock or type CMultiLock in your resource's access member function. Then call the lock object's Lock member function (for example, CSingleLock::Lock). At this point, your thread will either gain access to the resource, wait for the resource to be released and gain access, or wait for the resource to be released and time out, failing to gain access to the resource. In any case, your resource has been accessed in a thread-safe manner. To release the resource, use the lock object's Unlock member function (for example, CSingleLock::Unlock), or allow the lock object to fall out of scope.

Alternatively, you can create a CSemaphore object stand-alone, and access it explicitly before attempting to access the controlled resource. This method, while clearer to someone reading your source code, is more prone to error.

7. 4 The working with event object

CEvent objects have two types: manual and automatic. A manual CEvent object stays in the state set by SetEvent or ResetEvent until the other function is called. An automatic CEvent object automatically returns to a nonsignaled (unavailable) state after at least one thread is released.

CEvent::CEvent( BOOL bInitiallyOwn = FALSE, BOOL bManualReset = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );

Parameters:

bInitiallyOwn   If TRUE, the thread for the CMultilock or CSingleLock object is enabled. Otherwise, all threads wanting to access the resource must wait.

bManualReset   If TRUE, specifies that the event object is a manual event, otherwise the event object is an automatic event.

lpszName   Name of the CEvent object. Must be supplied if the object will be used across process boundaries. If the name matches an existing event, the constructor builds a new CEvent object which references the event of that name. If the name matches an existing synchronization object that is not an event, the construction will fail. If NULL, the name will be null.

lpsaAttribute   Security attributes for the event object.

To use a CEvent object, construct the CEvent object when it is needed. Specify the name of the event you wish to wait on, and that your application should initially own it. You can then access the event when the constructor returns. Call SetEvent to signal (make available) the event object and then call Unlock when you are done accessing the controlled resource.

An alternative method for using CEvent objects is to add a variable of type CEvent as a data member to the class you wish to control. During construction of the controlled object, call the constructor of the CEvent data member specifying if the event is initially signaled, the type of event object you want, the name of the event (if it will be used across process boundaries), and desired security attributes.

To access a resource controlled by a CEvent object in this manner, first create a variable of either type CSingleLock or type CMultiLock in your resource's access member function. Then call the lock object's Lock member function (for example, CMultiLock::Lock). At this point, your thread will either gain access to the resource, wait for the resource to be released and gain access, or wait for the resource to be released and time out, failing to gain access to the resource. In any case, your resource has been accessed in a thread-safe manner. To release the resource, call SetEvent to signal the event object, and then use the lock object's Unlock member function (for example, CMultiLock::Unlock), or allow the lock object to fall out of scope.

The program in Listing 7.4 demonstrates the threads implementation in different forms. The threads make the string information displaying in the working field of program. The end of every thread is signalized by dialog box.

Listing 7.4 The program with different threads// theads.h: interface for the CMain class.

class CMain : public CFrameWnd

{public:

void Art(char *,int);

int m_X,m_Y;

CSemaphore Sema;

CEvent Event;

CCriticalSection cs;

// CSingleLock SyncOb;

afx_msg void OnExit();

afx_msg void OnPaint();

afx_msg void

OnRButtonDown(UINT Flags,CPoint Loc);

afx_msg void OnThreads1();

CMain();

virtual ~CMain();

DECLARE_MESSAGE_MAP()

};

class CApp : public CWinApp

{public:

BOOL InitInstance();

};

class CSampleD : public CDialog

{public:

CSampleD(UINT id,CWnd *p) : CDialog(id,p){}

CSampleD():CDialog(){}

};

// threads.cpp: implementation of the CMain class.

#include <afxwin.h>

#include <afxmt.h>

#include "theads.h"

#include "resource.h"

//////////////////////////////////////////////////////////////////////

UINT ThirdThread(LPVOID WinObjPtr);

UINT FourthThread(LPVOID WinObjPtr);

UINT FifthThread(LPVOID WinObjPtr);

UINT SixthThread(LPVOID WinObjPtr);

int maxX,maxY;

CMain::CMain()

{Create(NULL,"Threads samples", WS_OVERLAPPEDWINDOW, rectDefault,

NULL, MAKEINTRESOURCE (IDR_MENU1));

m_X=m_Y=0;

maxX=GetSystemMetrics(SM_CXSCREEN);

maxY=GetSystemMetrics(SM_CYSCREEN);

}

BEGIN_MESSAGE_MAP(CMain,CFrameWnd)

ON_WM_PAINT()

ON_COMMAND(ID_THREADS1,OnThreads1)

ON_COMMAND(ID_THREADS2,OnThreads2)

ON_COMMAND(ID_EXIT,OnExit)

END_MESSAGE_MAP()

//////////////////////////////////////////////////////////////////////

BOOL CApp::InitInstance()

{m_pMainWnd=new CMain;

m_pMainWnd->ShowWindow(m_nCmdShow);

m_pMainWnd->UpdateWindow();

return TRUE;

}

CApp App;

void CMain::OnThreads1()

{AfxBeginThread(ThirdThread,this);

AfxBeginThread(FourthThread,this);}

void CMain::OnThreads2()

{AfxBeginThread(SixthThread,this);

AfxBeginThread(FifthThread,this);}

void CMain::OnPaint()

{CPaintDC dc(this);

dc.BitBlt(0, 0, maxX, maxY,

&memDC, 0, 0, SRCCOPY);}

void CMain::OnExit()

{int i=MessageBox("Quit the program?", "Exit", MB_YESNO);

if(i==IDYES)SendMessage(WM_CLOSE);}

UINT ThirdThread(LPVOID WinObjPtr)

{CMain *ptr=(CMain*)WinObjPtr;

CSingleLock SyncOb(&(ptr->Event));

char a[255];

int i;

SyncOb.Lock();

for(i=0;i<30;i++)

{Sleep(400);

wsprintf(a,"First flow %d",i);

ptr->memDC.TextOut(1,i*10,a,strlen(a));

ptr->InvalidateRect(NULL); }

ptr->MessageBox("End of third Process","3");

SyncOb.Unlock();

return 0;

}

UINT FourthThread(LPVOID WinObjPtr)

{CMain *ptr=(CMain*)WinObjPtr;

char a[255];

int i;

for(i=0;i<30;i++)

{if(i==10)ptr->Event.SetEvent();

Sleep(500);

wsprintf(a,"Second flow %d",i);

ptr->memDC.TextOut(250,i*10,a,strlen(a));

ptr->InvalidateRect(NULL);

}

ptr->MessageBox("End of fourth Process","4");

return 0;

}

UINT FifthThread(LPVOID WinObjPtr)

{CMain *ptr=(CMain*)WinObjPtr;

char a[255]="FifthThread";

ptr->Art(a,1);

return 0;

}

UINT SixthThread(LPVOID WinObjPtr)

{ CMain *ptr=(CMain*)WinObjPtr;

char a[255]="SixthThread";

ptr->Art(a,250);

return 0;

}

void CMain::Art(char *b,int r)

{int i;

char a[255];

// CSingleLock SyncOb(&cs);

// SyncOb.Lock();

cs.Lock();

for(i=0;i<30;i++)

{Sleep(400);

wsprintf(a,"%s %d",b,i);

memDC.TextOut(r,i*10,a,strlen(a));

InvalidateRect(NULL);

}

// SyncOb.Unlock();

cs.Unlock();}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]