Click here to Skip to main content
15,885,278 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
Hi all

i ve code which read 10 files at a time and apply multithreading for doing operation of applying multithreading

the problem is this place where i use multithrading i want to apply lock and lock
because without applying locking

my system speed drastically down and cpu use its 100% processing

kindly guide me how apply locking and unlocking
C++
long   WINAPI    Thread(long lParam);

CString fileName="";
CString outFilePath="";
HANDLE      hThread[10];
DWORD          dwID[10];
DWORD     dwRetVal = 0;
int TotalThreadWorking=0;

// function which is called in thread creation  below named ThreadTwo

long WINAPI ThreadTwo(long lParam)
{
  
	       classMain classMainObj;
	       classMainObj.MainFunction(fileName,outFilePath);
		   TotalThreadWorking--;
		   cout<<"Thread Count is "<<TotalThreadWorking<<endl;
	
 	return 0;
}

void test()
{
	 // here do directory scanning //

	   CFileFind find;
	   CString inpath="C:\\TestFile";
	   CString outFolderPath=inpath+"_out";
	
	   CreateDirectory(outFilePath,NULL);
	   if(inpath.Right(1) != "\\")
		   inpath += "\\";
	   inpath += "*.*";
	   BOOL found = find.FindFile(inpath);

// here find files from the given folder//	
	
   while (found )
	   {
		   if(TotalThreadWorking<10)   // chek for 10 files
		   {
      		   found = find.FindNextFile();
		   if(find.IsDots())
		   continue;
		    


		   fileName =find.GetFilePath();
		   outFilePath=outFolderPath+"\\"+find.GetFileName()+"_dec";
		  
		    // thread creation as my opinon lock apply here not confirm 
                    // how to apply and where to apply  

			   hThread[TotalThreadWorking] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadTwo,NULL,0,&dwID[TotalThreadWorking]);   // here is the function of Thread Two called
                        .........

  
    // unlock apply here as my opinion 

		   TotalThreadWorking++;



		   }
		   else
		   {
			   Sleep(1000);
		   }
			   
      
	   }
	  
  
	   
}

kindly help how to apply lock and unlock and where to apply lock and unlock
Posted
Updated 28-Aug-12 20:20pm
v3

Locks are used to control access to data, to prevent race conditions, and to have threads wait until an event has occurred.

From your code snippet, I can't be certain, but I'm guessing that your high CPU times occur because you have ten threads actively working at the same time. they are keeping your CPU really busy.

Inside the loop in your worker threads, try adding Sleep(1). This will cause the thread to give up it's time slice for at least one millisecond. You might increase the value if you need to.
 
Share this answer
 
For the first: you should know what you want to lock. At most times you should lock resources that you would use at once. For instance an output file stream to prevent the mixed output of two threads. I.e. Thread-A writes AAAA and Thread-B writes BBBB this would possible the unlocked output of ABABABAB. Thats not what you want therefore you should lock the output. The aim is to commit the result of an operation at once. The output resource can be very different. This can be a file stream, any other stream, databases, services, system functions and so on. To minimize the lock time you should lock the resource immediate when you open it and unlock when the resource is closed.
The following example illustrates the locking of a output file usage by different threads. All the threads write the thread result to the output file.
Most of the code is decoration (but works) to illustrate a multithread processing of files.
The most important classes are: CDataLock and CMainObject.
The CMainObject executes a task on a file and prints the result to the output file with locking it by CDataLock.
In most cases the usage of mutex objects are the best choice. They can be shared among threads and proccesses too (named mutex objects).

This example walks over all directories in drive C:\ and counts all bytes 'A' in the found header (*.h) files. The results are written to C:\Temp\log.txt (hint: enshure the path exist).

#pragma once
#include <stdio.h>
#include <tchar.h>
#include <windows.h>

#ifdef _DEBUG
	#include <crtdbg.h>
	#define	START()	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF);
#else
	#define	START()	
#endif

//////////////////////////////////
// CDataLock
class CDataLock
{
public:
	typedef HANDLE	LOCKOBJECT;

public:
	CDataLock(LOCKOBJECT& lockobject)						{ _hlock=lockobject; if(_hlock) WaitForSingleObject(_hlock,INFINITE); }
	~CDataLock()																{ if(_hlock) ReleaseMutex(_hlock); }
	static void	Init(LOCKOBJECT& lockobject)		{ lockobject = CreateMutex(0,0,0); }
	static void	Exit(LOCKOBJECT& lockobject)		{ if(lockobject) CloseHandle(lockobject); }
private:
	LOCKOBJECT		_hlock;
};

//////////////////////////////////
// CMainObject
class CMainObject
{
	enum{ SEARCH_BYTE = 'A', };
public:
	CMainObject(const TCHAR* infile,const TCHAR* outfile,CDataLock::LOCKOBJECT& lock);
	~CMainObject();

public:
	static LONG FAR PASCAL __fnThread(void* p){ return p?((CMainObject*)p)->Thread():0; }

protected:
	virtual long	Thread();
	void					Print(const TCHAR* format,...);

private:
	CDataLock::LOCKOBJECT		_lock;
	TCHAR*									_infile;
	TCHAR*									_outfile;
};

CMainObject::CMainObject(const TCHAR* infile,const TCHAR* outfile,CDataLock::LOCKOBJECT& lock):_lock(lock)
{
	_infile  = _tcsdup(infile?infile:__TEXT(""));
	_outfile = _tcsdup(outfile?outfile:__TEXT(""));
}

CMainObject::~CMainObject()
{
	if(_infile) free(_infile);
	if(_outfile) free(_outfile);
}

long CMainObject::Thread()
{
	HANDLE				h = ::CreateFile(_infile,GENERIC_READ,0,0,OPEN_EXISTING,0,0);
	if(INVALID_HANDLE_VALUE!=h)
	{
		unsigned char	readbuff[0x1000];
		unsigned long	readlen,ix;
		unsigned int	count = 0;
		
		while(::ReadFile(h,readbuff,sizeof(readbuff),&readlen,0) && (0<readlen))
		{
			for(ix=0;ix<readlen;ix++)
			{
				if(SEARCH_BYTE==readbuff[ix])
					++count;
			}
		}

		CloseHandle(h);
		Print(__TEXT("%c - %i times found in: %s\r\n"),(TCHAR)SEARCH_BYTE,count,_infile);
	}

	return 0;
}

void CMainObject::Print(const TCHAR* format,...)
{
	CDataLock			l(_lock);
	HANDLE				h = ::CreateFile(_outfile,GENERIC_WRITE,0,0,OPEN_ALWAYS,0,0);
	if(INVALID_HANDLE_VALUE!=h)
	{
		unsigned long		w = 0;
		va_list					val;
		TCHAR						f[0x1000];
		int							l;

		va_start(val,format);
		l = _vsntprintf_s(f,sizeof(f)/sizeof(f[0]),_TRUNCATE,format,val);
		va_end(val);
		if(0==SetFilePointer(h,0,0,FILE_END))
		{
			if(sizeof(short)==sizeof(TCHAR))
			{
				unsigned short	unicode = 0xFeFF;
				WriteFile(h,(void*)&unicode,2,&w,0);
			}
		}
		WriteFile(h,(void*)f,l*sizeof(TCHAR),&w,0);
		CloseHandle(h);
	}
}

//////////////////////////////////
// CThreadArray
class CThreadArray
{
public:
	CThreadArray(const TCHAR* outfile);
	~CThreadArray();
	
	void					Add(const TCHAR* infile);

private:
	unsigned int	NextFree();
	unsigned int	Wait(const int waitall,const unsigned long timeout);

private:
						enum{ MAX_THREADS=MAXIMUM_WAIT_OBJECTS /* see: WaitForMultipleObjects */, };
	HANDLE									_ahThreads[MAX_THREADS];
	CMainObject*						_apThreads[MAX_THREADS];
	unsigned int						_nhThreads;
	const TCHAR*						_outfile;
	CDataLock::LOCKOBJECT		_lock;
};

CThreadArray::CThreadArray(const TCHAR* outfile)
{
	CDataLock::Init(_lock);
	_outfile   = outfile;
	_nhThreads = 0;
	::DeleteFile(_outfile);
}

CThreadArray::~CThreadArray()
{
	unsigned int	ix;
	Wait(1,INFINITE);
	for(ix=0;ix<_nhThreads;ix++)
	{
		delete _apThreads[ix];
	}
	CDataLock::Exit(_lock);
}

unsigned int CThreadArray::Wait(const int waitall,const unsigned long timeout)
{
	unsigned int	wr = WaitForMultipleObjects(_nhThreads,_ahThreads,waitall,timeout);
	return (wr>=WAIT_OBJECT_0) && (wr<(WAIT_OBJECT_0+_nhThreads))?wr-WAIT_OBJECT_0:-1;
}

unsigned int CThreadArray::NextFree()
{
	unsigned int	wr;
	unsigned int	ix = 0;
	if(_nhThreads<MAX_THREADS) return _nhThreads++;
	while(0<_nhThreads)
	{
		wr = Wait(0,INFINITE);
		if(wr<_nhThreads)
		{
			ix = wr;
			break;
		}
	}
	if(ix<_nhThreads)
	{
		delete _apThreads[ix];
		_apThreads[ix] = 0;
		_ahThreads[ix] = 0;
	}
	return ix;
}

void CThreadArray::Add(const TCHAR* infile)
{
	unsigned int	ix = NextFree();
	unsigned long	tid;

	_apThreads[ix] = new CMainObject(infile,_outfile,_lock);
	_ahThreads[ix] = CreateThread(0,0,(LPTHREAD_START_ROUTINE)CMainObject::__fnThread,_apThreads[ix],0,&tid);

	#ifdef _DEBUG
	_tprintf(__TEXT("%s\r\n"),infile); // is threadsafe
	#endif
}

//////////////////////////////////
// vWalkFs
class vWalkFs
{
public: // vWalkFS
	virtual int		Enter(const TCHAR* filename,WIN32_FIND_DATA& fd) = 0;
	virtual int		Leave(const TCHAR* filename,WIN32_FIND_DATA& fd) = 0;
	
	static void	Walk(const TCHAR* path,const TCHAR* filter,vWalkFs& walk);
private:
	static void	Walk(TCHAR* path,const unsigned int cpath,const unsigned int lpath,const TCHAR* filter,const unsigned int lfilter,vWalkFs& walk);
};

void vWalkFs::Walk(const TCHAR* path,const TCHAR* filter,vWalkFs& walk)
{
	TCHAR		full[0x1000];
	_tcscpy_s(full,sizeof(full)/sizeof(full[0]),path);
	Walk(full,sizeof(full)/sizeof(full[0]),_tcslen(full),filter,_tcslen(filter),walk);
}

void vWalkFs::Walk(TCHAR* path,const unsigned int cpath,const unsigned int lpath,const TCHAR* filter,const unsigned int lfilter,vWalkFs& walk)
{
	typedef struct { static int dot(const TCHAR* s){ for(;'.'==*s;s++); return 0==*s?1:0; } } is;
	HANDLE					hf;
	WIN32_FIND_DATA	fd;
	unsigned int		lf,ll = lpath;

	if(!lpath) return;
	if((lfilter+lpath+1)>cpath) return;

	if('\\'!=path[ll-1]) path[ll++] = '\\';
	_tcscpy_s(path+ll,cpath-ll,filter);

	hf = FindFirstFile(path,&fd);
	if(INVALID_HANDLE_VALUE!=hf)
	{
		do
		{
			if(!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
			{
				lf = _tcslen(fd.cFileName);
				if((ll+lf+1)<cpath)
				{
					_tcscpy_s(path+ll,cpath-ll,fd.cFileName);
					if(!walk.Enter(path,fd)) break;
					walk.Leave(path,fd);
				}
			}
		} while(FindNextFile(hf,&fd));
		FindClose(hf);
	}

	_tcscpy_s(path+ll,cpath-ll,__TEXT("*.*"));
	hf = FindFirstFile(path,&fd);
	if(INVALID_HANDLE_VALUE!=hf)
	{
		do
		{
			if((fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && !is::dot(fd.cFileName))
			{
				lf = _tcslen(fd.cFileName);
				if((ll+lf+1)<cpath)
				{
					_tcscpy_s(path+ll,cpath-ll,fd.cFileName);
					if(!walk.Enter(path,fd)) break;
					Walk(path,cpath,ll+lf,filter,lfilter,walk);
					walk.Leave(path,fd);
				}
			}
		} while(FindNextFile(hf,&fd));
		FindClose(hf);
	}
	path[lpath] = 0;
}


//////////////////////////////////
// CWalkFs
class CWalkFs : public vWalkFs
{
public:
	virtual int	Enter(const TCHAR* filename,WIN32_FIND_DATA& fd)
	{
		if(!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
			_ta.Add(filename);
		return 1;
	}
	virtual int Leave(const TCHAR* filename,WIN32_FIND_DATA& fd)
	{
		return 1;
	}
	
	CWalkFs(CThreadArray& ta):_ta(ta){}
private:
	CThreadArray&	_ta;
};

//////////////////////////////////
// main
int _tmain(int argc, _TCHAR* argv[])
{
	/****/ START()

	CThreadArray	ta(__TEXT("C:\\Temp\\log.txt"));
	CWalkFs				walk(ta);

	vWalkFs::Walk(__TEXT("C:\\"),__TEXT("*.h"),walk);

	_tprintf(__TEXT("<key>")); _gettch();
	return 0;
}


Good luck and best regards.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900