C ++ Windows Threading и проблема мьютекса - PullRequest
1 голос
/ 15 ноября 2011

Я немного заржавел с резьбовыми программами, особенно в Windows. Я создал простой mex-файл в Matlab, предназначенный для чтения нескольких файлов, каждый из которых читается в отдельном потоке. Файл не делает ничего действительно полезного, но является предшественником более сложной версии, которая будет использовать все функции, которые я включил в этот файл. Вот код:

#include <windows.h>
#include "mex.h"
#include <fstream>

typedef unsigned char uchar;
typedef unsigned int uint;

using namespace std;

int N;
int nThreads;
const int BLOCKSIZE = 1024;
char * buffer;
char * out;
HANDLE    hIOMutex;

DWORD WINAPI runThread(LPVOID argPos) {
    int pos = *(reinterpret_cast<int*>(argPos));

    DWORD dwWaitResult = WaitForSingleObject( hIOMutex, INFINITE );

    if (dwWaitResult == WAIT_OBJECT_0){
        char buf[20];
        sprintf(buf, "test%i.dat", pos);
        ifstream ifs(buf, ios::binary);

        if (!ifs.fail()) {
            mexPrintf("Running thread:%i\n", pos);
            for (int i=0; i<N/BLOCKSIZE;i++) {
                if (ifs.eof()){ 
                    mexPrintf("File %s exited at i=%i\n", buf, (i-1)*BLOCKSIZE);
                    break;
                }
                ifs.read(&buffer[pos*BLOCKSIZE], BLOCKSIZE);
            }
        }
        else {
            mexPrintf("Could not open file %s\n", buf);
        }

        ifs.close();
        ReleaseMutex( hIOMutex);
    }
    else
        mexPrintf("The Mutex failed in thread:%i \n", pos);


    return TRUE;
}

// 0 - N is data size
// 1 - nThreads is number of threads
// 2 - this is the output array

void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[] ) {
    N = mxGetScalar(prhs[0]);
    nThreads = mxGetScalar(prhs[1]);
    out = (char*)mxGetData(prhs[2]);
    buffer = (char*)malloc(BLOCKSIZE*nThreads);
    hIOMutex= CreateMutex(NULL, FALSE, NULL);

    HANDLE *hArr = (HANDLE*)malloc(sizeof(HANDLE)*nThreads);
    int *tInd = (int*)malloc(sizeof(int)*nThreads);

    for (int i=0;i<nThreads;i++){
        tInd[i]=i;
        hArr[i] = CreateThread( NULL, 0, runThread, &tInd[i], 0, NULL);
        if (!hArr[i]) {
            mexPrintf("Failed to start thread:%i\n", i);
            break;
        }
    }

    WaitForMultipleObjects( nThreads, hArr, TRUE, INFINITE);

    for (int i=0;i<nThreads;i++)
        CloseHandle(hArr[i]);

    CloseHandle(hIOMutex);
    mexEvalString("drawnow");
    mexPrintf("Finished all threads.\n");

    free(hArr);
    free(tInd);
    free(buffer);

Я собираю это так в Matlab:

mex readFile.cpp

А затем запустите его так:

out = zeros(1024*1024,1,'uint8'); 
readFile(1024*1024,nFiles,out);

Проблема в том, что когда я устанавливаю nFiles равным или меньшим 64, все работает как положено, и я получаю следующий вывод:

Running thread:0
.
.
.
Running thread:62
Running thread:63
Finished all threads.

Однако, когда я устанавливаю nFiles на 65 или больше, я получаю:

Running thread:0
Running thread:1
Running thread:2
Running thread:3
The Mutex failed in thread:59 
The Mutex failed in thread:60 
The Mutex failed in thread:61 
.
.
.
(up to nFiles-1)
Finished all threads.

Я также проверил его без потоков, и он отлично работает.

Я не могу понять, что я делаю неправильно или почему прекращение использования мьютекса было бы настолько произвольным, поэтому я предполагаю, что есть кое-что, что я не принимаю во внимание. Кто-нибудь может увидеть, где у меня есть вопиющая ошибка, связанная с ошибкой, которую я вижу?

1 Ответ

3 голосов
/ 15 ноября 2011

В документации для WaitForMultipleObjects "Максимальное количество дескрипторов объектов - MAXIMUM_WAIT_OBJECTS.", Что в большинстве систем равно 64.

Это также (почти) дубликатиз этой темы .На самом деле, сводка да, ограничение 64, а также использование информации из раздела замечаний WaitForMultipleObjects для построения дерева потоков, которые нужно ждать.

...