#include "stdafx.h"
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <conio.h>
#include <stdlib.h>
using namespace std;

#define MAX_THREADS 3
#define BUF_SIZE 255
#define nRows 10

DWORD WINAPI MyThreadFunction( LPVOID lpParam );
void ErrorHandler(LPTSTR lpszFunction);
void ConsoleOutput(double _time);
void FileOutput();

int nRowsOnProc;
double **partMatr;//, **partMu;
double *buf;
int *map;
long double det;
FILE *U;

HANDLE _mutex = CreateMutex(NULL, FALSE, NULL);

struct SyncInfo
{
    SyncInfo(int threadsCount) : Awaiting(threadsCount), ThreadsCount(threadsCount), Semaphore(::CreateSemaphore(0, 0, 1024, 0)) {};
    ~SyncInfo() { ::CloseHandle(this->Semaphore); }
    volatile unsigned int Awaiting; 
    const int ThreadsCount;
    const HANDLE Semaphore;
};

static void RandezvousOthers(SyncInfo &sync)
{
    if (0 == ::InterlockedDecrement(&(sync.Awaiting))) { 
        sync.Awaiting = sync.ThreadsCount;
        ::ReleaseSemaphore(sync.Semaphore, sync.ThreadsCount - 1, 0); 
    }
    else {
        ::WaitForSingleObject(sync.Semaphore, INFINITE); 
    }
}

SyncInfo sync(MAX_THREADS);

int _tmain(int argc, _TCHAR* argv[])
{
    DWORD   dwThreadIdArray[MAX_THREADS];
    HANDLE  hThreadArray[MAX_THREADS];

	_cputs("Begin\n");
	nRowsOnProc=1 + nRows / MAX_THREADS;
	partMatr=new double*[nRows];
	//partMu=new double*[nRowsOnProc];
	buf=new double[nRows];
	map=new int[nRows];
	for(int i=0; i<nRows; i++)
	{
		partMatr[i]=new double[nRows];
		map[i]=i % MAX_THREADS;
	}

	::srand(::GetTickCount()); 
	for(int i=0; i<nRows; i++)
	{
		for(int j=0; j<nRows; j++)
		{
			partMatr[i][j] = -100 + rand() % 200;
			//partMatr[i][j] /= 1000;
		}
	}
	

	__int64 freq, start,end,diff;
	QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
	QueryPerformanceCounter((LARGE_INTEGER*)&start);
	_cputs("In process...\n");

	int thNumbers[MAX_THREADS];
    for( int i=0; i<MAX_THREADS; i++ )
    {
		thNumbers[i] = i;
        hThreadArray[i] = CreateThread( 
            NULL,                   // default security attributes
            0,                      // use default stack size  
			MyThreadFunction,
			&thNumbers[i],
            0,                      // use default creation flags 
            &dwThreadIdArray[i]);   // returns the thread identifier 

        if (hThreadArray[i] == NULL) 
        {
           ErrorHandler(TEXT("CreateThread"));
           ExitProcess(3);
        }
    } 

    WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);

	det = 1;
	for(int i = 0; i < nRows; i++)
		det *= partMatr[i][i];

	QueryPerformanceCounter((LARGE_INTEGER*)&end);
	diff = ((end - start) * 1000) / freq;
	unsigned int milliseconds = (unsigned int)(diff & 0xffffffff);

	FileOutput();
	ConsoleOutput((double)milliseconds/1000);

    for(int i=0; i<MAX_THREADS; i++)
    {
        CloseHandle(hThreadArray[i]);
    }
	CloseHandle(_mutex);
	_getch();
	return 0;
}

void FileOutput()
{
	fopen_s(&U, "u.txt", "w");
	for(int i=0; i<nRows; i++)
	{
		for(int j=0; j<nRows; j++)
			if(j >= i)
				fprintf(U, "%f ", partMatr[i][j]);
			else
				fprintf(U, "0 ");
		fprintf(U, "\n");
		delete [] partMatr[i];
	}
	fclose(U);
}

void ConsoleOutput(double _time)
{
	_cprintf("Det = %Lf\n", det);
	_cprintf("Time = %f\n", _time);
	_cputs("End. Press Enter...");
}

DWORD WINAPI MyThreadFunction( LPVOID lpParam ) 
{ 
	int th;
	th = *((int *)(lpParam));
	double mu;

	for (int k = 0; k < nRows - 1; k++)
	{
		for (int i =0; i < nRows; i++)
		{
			if (map[i] == th)
			{
				mu = partMatr[i / MAX_THREADS][k] / partMatr[k / MAX_THREADS][k];
				for (int j = k; j < nRows; j++)
					partMatr[i / MAX_THREADS][j] -= mu * partMatr[k / MAX_THREADS][j];
			}
		}
		RandezvousOthers(sync);
	}
	
    return 0; 
} 

void ErrorHandler(LPTSTR lpszFunction) 
{ 
    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError(); 

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
        (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) lpszFunction) + 40) * sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)lpDisplayBuf, 
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("%s failed with error %d: %s"), 
        lpszFunction, dw, lpMsgBuf); 
    MessageBox(NULL, (LPCTSTR) lpDisplayBuf, TEXT("Error"), MB_OK); 

    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
}

Соседние файлы в папке lab3