Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/15: Рейтинг темы: голосов - 15, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 29.08.2015
Сообщений: 4

Написать консольную программу для генерации сигнатуры указанного файла (задействовать параллелизм)

20.09.2016, 22:47. Показов 3277. Ответов 5
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте, дорогие форумчане.

На днях подкинули заданице:

Требуется написать консольную программу на C++ для генерации сигнатуры указанного файла. Сигнатура генерируется следующим образом: исходный файл делится на блоки равной (фиксированной) длины (если размер файла не кратен размеру блока, последний фрагмент может быть меньше или дополнен нулями до размера полного блока). Для каждого блока вычисляется значение hash функции и дописывается в выходной файл-сигнатуру.

Так вроде ничего сложного, кроме следующего требования к этому заданию:
1. Следует максимально оптимизировать скорость работы утилиты с учетом работы в многопроцессорной среде

Мне ввиду специфики работы, с потоками, параллелизмом и boost'ом общаться не приходилось.
Может кто подсказать, в какую сторону вообще смотреть?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.09.2016, 22:47
Ответы с готовыми решениями:

Нужно написать консольную программу для нахождения значения F в заданном промежутке с шагом 0,5
Здравствуйте, уважаемые программисты! Прошу у Вас помощи, помогите пожалуйста! Нужно написать консольную программу для нахождения...

Написать программу для автоматической генерации методов
Дан текстовый файл, содержащий исходный код программы на языке Java. Написать программу для автоматической генерации методов get, set,...

Написать консольную программу
Народ помогите плз :) Напишите консольную программу которая считывает с консоли целое число , затем - цифру и определяет, сколько раз эта...

5
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
21.09.2016, 16:49
Цитата Сообщение от Kap98k Посмотреть сообщение
Может кто подсказать, в какую сторону вообще смотреть?
В сети мало примеров работы с потоками или с объектами синхронизации?
0
0 / 0 / 0
Регистрация: 29.08.2015
Сообщений: 4
28.09.2016, 10:59  [ТС]
Цитата Сообщение от shmkv Посмотреть сообщение
В сети мало примеров работы с потоками или с объектами синхронизации?
Тут не поспоришь, но когда не сталкивался вообще с этим, то трудно решить с чем работать WinApi, boost или еще чем
Пока решил пользоваться thread из STL, чтобы абстрагироваться от платформы (а может это иллюзия ).

Возник вопрос следующего характера.
Создается отдельный поток на чтение из файла, потоку передаем функцию (код ниже).
Поток отсоединяется и работает в фоне. С маленькими файлами проблем нет (в пределах 10 - 20 Мб).
А вот при чтении файла в 110 Мб регулярно вылетает ios:failure.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void SignCreater::readFile(){
    try{
        if(!hInnerFile){
            //здесь что то должно быть
        }
        else
        {
            while(!hInnerFile.good()){
                //blockSize  вводится пользователем.
                shared_ptr<char> pInBlock(new char [blockSize], [](char * buf) {delete[] buf;});
                hInnerFile.read(pInBlock.get(), blockSize); 
                //две очереди для передачи данных другим потокам
                fifoWrite.push(pInBlock);
                fifoHash.push(pInBlock);
            }
            //atomic для синхронизации
            finish.store(true);
            hInnerFile.close();
 
        }
    }
    catch(system_error &err){
 
    }
}
Подскажите, где я дурак?
0
1378 / 522 / 72
Регистрация: 21.07.2015
Сообщений: 1,308
28.09.2016, 14:57
Цитата Сообщение от Kap98k Посмотреть сообщение
то трудно решить с чем работать WinApi, boost или еще чем
Работа с потоками и с синхронизацией поддерживается всеми современными С++11(14) компиляторами "из коробки". Используй шатный std::thread. WinApi - это непереносимо и имеет смыл использовать лишь если нужна супер оптимизация под винду.

Добавлено через 16 минут
Цитата Сообщение от Kap98k Посмотреть сообщение
Подскажите, где я дурак?
А если просто без потоков эту функцию запускаешь, то работает? Просто тут ты отрывок дал и не видно как из других потоков ты с этим хозяйством взаимодействуешь.
1
0 / 0 / 0
Регистрация: 29.08.2015
Сообщений: 4
28.09.2016, 18:59  [ТС]
Цитата Сообщение от shmkv Посмотреть сообщение
абота с потоками и с синхронизацией поддерживается всеми современными С++11(14) компиляторами "из коробки". Используй шатный std::thread. WinApi - это непереносимо и имеет смыл использовать лишь если нужна супер оптимизация под винду.
Вот там, где я сейчас работаю с современными компиляторами беда. А тут за это задание взялся и понял, что работал больше с Си, чем С++ и STL.

Цитата Сообщение от shmkv Посмотреть сообщение
если просто без потоков эту функцию запускаешь, то работает? Просто тут ты отрывок дал и не видно как из других потоков ты с этим хозяйством взаимодействуешь.
Сама функция работает криво, неважно в потоке или нет. Вроде нашел место:

C++
1
shared_ptr<char> pInBlock(new char [blockSize], [ ](char * buf) {delete [ ] buf;});
потому что, если заменить этот "умный" указатель на

C++
1
char * pInBlock = new char [blocksize];
то работает адекватно и нормально видит конец файла, не уходя в бесконечный цикл (хотя вроде умный указатель инициализирую как надо).


Кликните здесь для просмотра всего текста
Очередь
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <queue>
#include <memory>
#include <mutex>
#include <condition_variable>
 
template <class T>
class tsQueue
{
private:
    mutable std::mutex trafLight;
    std::queue<T> fifo;
    std::condition_variable tCondition;
 
public:
    tsQueue(){}
    tsQueue(tsQueue const& another){
        std::lock_guard<std::mutex> lk(another.trafLight);
        fifo = another.fifo;
    }
 
    tsQueue& operator= (const tsQueue&) = delete;
 
    void push (T new_value){
        std::lock_guard<std::mutex> lk(trafLight);
        fifo.push(new_value);
        tCondition.notify_one();
    }
 
    void pop (T& value){
        std::unique_lock<std::mutex> lk(trafLight);
        tCondition.wait(lk, [this]{return !fifo.empty();});
        value = fifo.front();
        fifo.pop();
    }
 
    T pop (){
        std::unique_lock<std::mutex> lk(trafLight);
        tCondition.wait(lk, [this]{return !fifo.empty();});
        T value = fifo.front();
        fifo.pop();
        return value;
    }
 
    bool empty()const {
        std::lock_guard<std::mutex> lk(trafLight);
        return fifo.empty();
    }
 
 
};

Кликните здесь для просмотра всего текста
Основной класс
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#ifndef SIGN_H
#define SIGN_H
 
#include <iostream>
#include <fstream>
#include <exception>
#include <stdexcept>
#include <thread>
#include <atomic>
 
#include "safequeu.h"
 
#define MAXLEN 128
#define DEFBLOCKSIZE 1024 // размер блока в Кб
 
using namespace std;
 
class SignCreater {
private:
    char innerFile [MAXLEN];
    char outerFile [MAXLEN];
    unsigned int blockSize;
    std::atomic<bool> finish;
    ifstream hInnerFile;
    ofstream hOuterFile;
    tsQueue<std::shared_ptr<char>> fifoWrite;
    tsQueue<std::shared_ptr<char>> fifoHash;
    tsQueue<unsigned int> fifoAnswerHash;
 
public:
    SignCreater(){
        finish.store(false);
        blockSize = DEFBLOCKSIZE * 1024;
        for (int i =0 ;i < MAXLEN; i++)
            innerFile[i]=0, outerFile[i]=0;
 
    }
    ~SignCreater(){
        if(hInnerFile.is_open())
            hInnerFile.close();
        if(hOuterFile.is_open())
            hOuterFile.close();
    }
 
    void processing();
    void getInOutFile();
    void readFile();
    void writeFile();
    uint32_t CRC32(unsigned char *block, unsigned int len);
 
};
 
 
#endif // SIGN_H

Кликните здесь для просмотра всего текста
Методы класса
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#include "signClass.h"
#include <future>
 
void SignCreater::getInOutFile(){
    char ch = 0;
 
    do {
        try {
            cout<<"Введите полный путь до входящего файла:"<<endl;
            cin.unsetf(ios::skipws);
            cin.getline(innerFile, MAXLEN);
            if(cin.good()){
                hInnerFile.exceptions(ios::failbit|ios::badbit|ios::eofbit);
                hInnerFile.open(innerFile, ios::out|ios::binary);
 
                cout<<"Enter path for outputfile: "<<endl;
                cin.getline(outerFile, MAXLEN);
                if(outerFile == 0){
                    cout<<"File will be create in local directory!"<<endl;
 
                }
                hOuterFile.exceptions(ios::failbit|ios::badbit);
                hOuterFile.open(outerFile, ios::in|ios::binary|ios::app);
 
                cout<< "Enter size of block (Kb): ";
                cin>>blockSize;
                if(cin.good())
                {
                    if(blockSize == 0){
                       blockSize = DEFBLOCKSIZE;
                    }
                    blockSize *= 1024;
                }
                break;
            }
 
        }
        catch (ios::failure &err){
            cerr<<"Ошибка: "<<err.what()<<endl;
            cerr<<"Невозможно найти или открыть Inner файл!"<<endl;
            cin.clear();
            cout<<"Хотите попробовать еще раз? y/n"<<endl;
            cin>>ch;
        }
        catch (range_error &err){
            cerr<<"Ошибка: "<< err.what()<<endl;
            cin.clear();
            cout<<"Хотите попробовать еще раз? y/n"<<endl;
            cin>>ch;
        }
    } while(ch == 'y');
}
 
void SignCreater::readFile(){
    unsigned int size;
 
    hInnerFile.seekg(0, ios::end);
    size = hInnerFile.tellg();
    hInnerFile.seekg(0, ios::beg);
 
    try{
        if(!hInnerFile.is_open()){
 //           throw system_error(errno);
        }
        else
        {
            int k=0;
            while(!hInnerFile.fail()&& !hInnerFile.eof()){
                if(size<blockSize)
                    blockSize = size;
                shared_ptr<char> pInBlock(new char [blockSize], [](char * buf) {delete[] buf;});
                hInnerFile.read(pInBlock.get(), blockSize);
                fifoWrite.push(pInBlock);
                fifoHash.push(pInBlock);
               size -= blockSize;
               ++k;
               cout<<k<<endl;
            }
            finish.store(true);
            hInnerFile.close();
 
        }
    }
    catch(system_error &err){
 
    }
}
 
//Функция перед запуском должна проверяться на наличие элементов в очереди
//Должна быть функция обрабатывающая очередь и передающая указатель блока на запись и подсчет хэша
 
void SignCreater::writeFile(){
    try{
        if(!hOuterFile){
            //здесь что то должно быть
        }
        else{
            hOuterFile.clear();
            while(!finish.load() && !fifoWrite.empty()){
                shared_ptr<char> pOutBlock(new char [2048], [] (char *buf){delete [] buf;});
                fifoWrite.pop(pOutBlock);
                hOuterFile.write(reinterpret_cast<char*>(pOutBlock.get()), 2048);
            }
            cout<<"Finish:"<<finish<<endl;
        }
    }
    catch (system_error &err){
 
    }
 
}
 
 
void SignCreater::processing(){
    this->getInOutFile();
 
    try {
        std::thread readingThread(&SignCreater::readFile, this);
            if(readingThread.joinable())
                readingThread.detach();
 
        std::thread writeThread(&SignCreater::writeFile, this);
            if(writeThread.joinable())
                writeThread.join();
 
    }
    catch(system_error& err){
        cerr<<"Error thread: "<<err.what()<<endl;
    }
}
0
0 / 0 / 0
Регистрация: 29.08.2015
Сообщений: 4
30.09.2016, 22:44  [ТС]
Итоговый рабочий вариант в приложении, может кому и пригодится.

shmkv спасибо за внимание к вопросу )
Вложения
Тип файла: zip Signature.zip (10.7 Кб, 112 просмотров)
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
30.09.2016, 22:44
Помогаю со студенческими работами здесь

Написать программу для распечатки на экране монитора указанного в варианте набора символ
Написать программу использую цикл for с использованием оператора для распечатки на экране монитора указанного в варианте набора символ без...

Написать программу для проверки указанного ниже свойства последовательности, вводимой с клавиатуры
Число вводимых элементов последовательности заранее неизвестно и определяется пользователем. Если последовательность обладает требуемым...

Написать программу, переводящую сумму в рублях в евро для указанного обменного курса
Написать программу, переводящую сумму в рублях в евро для указанного обменного курса. Ответ вывести в виде: «R руб. = E евро.». Вместо...

Консольную программу написать в графическом интерфейсе
Прошу Вашей помощи, так как не работал c++ builder. Программу написал консольную, но сказали переделать, как в графическом интерфейсе, я...

Написать программу оператора цикла for для распечатки на экране монитора указанного в варианте набора символов
A B C D E E A C D E E D A D E E D C A E E D C B A


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
Новые блоги и статьи
Символьное дифференцирование
igorrr37 13.02.2026
/ * Логарифм записывается как: (x-2)log(x^2+2) - означает логарифм (x^2+2) по основанию (x-2). Унарный минус обозначается как ! */ #include <iostream> #include <stack> #include <cctype>. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL3_image
8Observer8 10.02.2026
Содержание блога Библиотека SDL3_image содержит инструменты для расширенной работы с изображениями. Пошагово создадим проект для загрузки изображения формата PNG с альфа-каналом (с прозрачным. . .
Установка Qt-версии Lazarus IDE в Debian Trixie Xfce
volvo 10.02.2026
В общем, достали меня глюки IDE Лазаруса, собранной с использованием набора виджетов Gtk2 (конкретно: если набирать текст в редакторе и вызвать подсказку через Ctrl+Space, то после закрытия окошка. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru