Форум программистов, компьютерный форум, киберфорум
Наши страницы
Boost C++
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.50/10: Рейтинг темы: голосов - 10, средняя оценка - 4.50
Mellotron
0 / 0 / 0
Регистрация: 10.09.2012
Сообщений: 31
#1

Вывод в терминал, 4 потока

19.11.2012, 00:39. Просмотров 1776. Ответов 9
Метки нет (Все метки)

Здравствуйте, для дисциплины ОС требовалось написать программу, рекурсивно копирующую содержимое одной папки в другую с сохранением структуры. Собственно, программа написана, но преподаватель требует синхронизировать вывод в консоль процесса копирования, и синхронизировать само копирование 4-мя потоками (мьютекс). Сам только начал разбираться, можете помочь? Заранее спасибо.

Вот код программы:

Кликните здесь для просмотра всего текста
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
namespace fs = boost::filesystem;
 
const char copyDir(boost::filesystem::path const & source, boost::filesystem::path const & destination)
{
    
    try
    {
        // Check whether the function call is valid
        if(!fs::exists(source) || !fs::is_directory(source)
        )
        {
            std::cerr << "Source directory " << source.string()
                << " does not exist or is not a directory." << std::endl
            ;
            return false;
        }
        if(fs::exists(destination))
        {
            std::cerr << "Destination directory " << destination.string()
                << " already exists." << std::endl
            ;
            return false;
        }
        // Create the destination directory
        if(!fs::create_directory(destination))
        {
            std::cerr << "Unable to create destination directory"
                << destination.string() << std::endl
            ;
            return false;
        }
    }
    catch(fs::filesystem_error const & e)
    {
        std::cerr << e.what() << std::endl;
        return false;
    }
    // Iterate through the source directory
    for(
        fs::directory_iterator file(source);
        file != fs::directory_iterator(); ++file
    )
    {
        try
        {
            fs::path current(file->path());
            if(fs::is_directory(current))
            {
                // Found directory: Recursion
                if(
                    !copyDir(
                        current,
                        destination / current.filename()
                    )
                )
                {
                    return false;
                }
            }
            else
            {
                // Found file: Copy
                fs::copy_file(
                    current,
                    destination / current.filename()
                );
                std::cout << "file " << current.filename() << " copied to " << destination << std::endl;
            }
        }
        catch(fs::filesystem_error const & e)
        {
            std::cerr << e.what() << std::endl;
        }
    }
    return true;    
}
 
int main()
{
    fs::path directory_src; // путь до копируемого файла
    std::cout << "Set directory from which to copy" << std::endl;
    std::cin >> directory_src;
 
    /*if ( !fs::is_directory(directory_src)) {
        std::cout << "No such directory" << std::endl;
        return EXIT_FAILURE;
    }*/
 
    fs::path directory_dest; // полный путь до директории в которую копируем файл
    std::cout << "Set destination directory" << std::endl;
    std::cin >> directory_dest;
 
 
    copyDir(fs::path(directory_src), fs::path(directory_dest));
 
    _getch();
    return 0;
}


P.S. Преподаватель рекомендовал сделать цикл для создания 4х потоков.

Добавлено через 5 часов 59 минут
Вот, что набыдлокодил:

Кликните здесь для просмотра всего текста
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
namespace fs = boost::filesystem;
 
int copy(const boost::filesystem::path & destination,  const boost::filesystem::path current)
{
                void lock();
                fs::copy_file(
                    current,
                    destination / current.filename()
                );
                std::cout << "file " << current.filename() << " copied to " << destination << std::endl;    
                void unlock();
}
 
const char copyDir(boost::filesystem::path const & source, boost::filesystem::path const & destination)
{
    
    boost::mutex io_mutex;
    
    try
    {
        
        // Проверка правильности вызова функции
        if(!fs::exists(source) || !fs::is_directory(source)
        )
        {
            
            std::cerr << "Source directory " << source.string()
                << " does not exist or is not a directory." << std::endl
            ;
            return false;
        }
        if(fs::exists(destination))
        {
            
            std::cerr << "Destination directory " << destination.string()
                << " already exists." << std::endl
            ;
            return false;
        }
        // Создание директории
        if(!fs::create_directory(destination))
        {
            
            std::cerr << "Unable to create destination directory"
                << destination.string() << std::endl
            ;
            return false;
        }
        
    }
    catch(fs::filesystem_error const & e)
    {
        std::cerr << e.what() << std::endl;
        return false;
    }
    // Проверка содержимого директории
    for(fs::directory_iterator file(source);
        file != fs::directory_iterator(); ++file)
    
    {       
        try
        {
            fs::path current(file->path());
            if(fs::is_directory(current))
            {
 
                // Рекурсия по нахождению директории
                if(
                    !copyDir(current, destination / current.filename()))
                {
                    return false;
                }
            }
            else
            {   
                std::vector<boost::thread *> z;
 
                for (int i = 0; i < 4; ++i)
                z.push_back(new boost::thread(copy(const boost::filesystem::path(destination), current.filename())));
 
                for (int i = 0; i < 4; ++i)
                 {
                   z[i]->join();
                   delete z[i];
                 }              
            }
        }
        catch(fs::filesystem_error const & e)
        {
            std::cerr << e.what() << std::endl;
        }
    }
    return true;    
}
 
int main()
{
    fs::path directory_src; // путь до копируемой директории
    std::cout << "Set directory from which to copy" << std::endl;
    std::cin >> directory_src;  
 
    fs::path directory_dest; // путь до директории, в которую копируем
    std::cout << "Set destination directory" << std::endl;
    std::cin >> directory_dest;
 
    copyDir(fs::path(directory_src), fs::path(directory_dest)); 
    
    _getch();
    return 0;
}


Никак не получается правильно передать аргументы функции, да и вообще не уверен, что функция правильная. Просто именно для неё и нужны потоки, а в теле класса как сделать потоки, пока не знаю.

Добавлено через 18 минут
Забыл добавить: функция copy
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
19.11.2012, 00:39
Ответы с готовыми решениями:

Терминал, вывод данных
Всех приветствую! Пытаюсь написать программу для работы с ком портом,...

Вывод строки в терминал
Пробую в терминал, из &quot;флэша&quot; вывести данные, строка за строкой с помощью...

Вывод данных в терминал
как вывести хотя бы тот же &quot;Hello, world&quot; в терминал? (Ubuntu, Netbeans)

Вывод символов ASCII в терминал
Добрый вечер господа возник вопрос связанный с выводом на экран зашифрованного...

Передача данных c МК51 по UART и вывод в терминал
Нужно передать 2-х байтовое число через UART по каналу RS-485 на терминал.

9
Avazart
Эксперт С++
7717 / 5626 / 549
Регистрация: 10.12.2010
Сообщений: 25,324
Записей в блоге: 17
19.11.2012, 02:33 #2
Вот собственно пример недавний boost::thread объясните нубу

Добавлено через 2 минуты
И если не ошибаюсь, то там ограничения есть на копирование boost::thread и соответственно его существование в векторе...
0
Mellotron
0 / 0 / 0
Регистрация: 10.09.2012
Сообщений: 31
24.11.2012, 17:47  [ТС] #3
Ну у меня в векторе и не накапливается бесконечное количество потоков. Кто-нибудь может помочь с передачей аргументов функции copy?
0
Avazart
Эксперт С++
7717 / 5626 / 549
Регистрация: 10.12.2010
Сообщений: 25,324
Записей в блоге: 17
24.11.2012, 18:21 #4
А при чем тут бесконечное количество? При перераспределении памяти выполняется копирование элементов
0
igorrr37
1867 / 1483 / 751
Регистрация: 21.12.2010
Сообщений: 2,473
Записей в блоге: 11
24.11.2012, 20:36 #5
Лучший ответ Сообщение было отмечено как решение

Решение

можно создать пул из четырех потоков, и при нахождении очередного файла ставить ф-цию копирования этого файла в очередь к пулу
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
#include <iostream>
#include <conio.h>
#include <boost/filesystem.hpp>
#define BOOST_THREAD_USE_LIB
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/ref.hpp>
namespace fs = boost::filesystem3;
 
boost::mutex mutex;
boost::asio::io_service io;
 
void copy(fs::path const& current, fs::path const& destination)
{
    boost::lock_guard<boost::mutex> guard(mutex);
    try
    {
        fs::copy(current, destination / current.filename());
        std::cout << "file " << current.filename() << " copied to " << destination
            << " by thread with id: " << boost::this_thread::get_id() << std::endl;
    }
    catch(std::exception const& e)
    {
        std::cerr << "Exception in copy thread: " << e.what() << std::endl;
    }
}
 
const char copyDir(fs::path const & source, fs::path const & destination)
{
    try
    {
        // Проверка правильности вызова функции
        if(!fs::exists(source) || !fs::is_directory(source)
        )
        {
            std::cerr << "Source directory " << source.string()
                << " does not exist or is not a directory." << std::endl;
            return false;
        }
        else if(fs::exists(destination))
        {
            std::cerr << "Destination directory " << destination.string()
                << " already exists." << std::endl;
            return false;
        }
        // Создание директории
        else if(!fs::create_directory(destination))
        {
            std::cerr << "Unable to create destination directory"
                << destination.string() << std::endl;
            return false;
        }
 
    }
    catch(fs::filesystem_error const & e)
    {
        std::cerr << "Exception in main thread: " << e.what() << std::endl;
        return false;
    }
    // Проверка содержимого директории
    for(fs::directory_iterator it(source); it != fs::directory_iterator(); ++it)
    {
        try
        {
            fs::path currentpath(it->path());
            if(fs::is_directory(currentpath))
            {
 
                // Рекурсия по нахождению директории
                if(!copyDir(currentpath, destination / currentpath.filename()))
                {
                    return false;
                }
            }
            else
            {
                io.post(boost::bind(copy, currentpath, destination)); // ставим copy в очередь пула
            }
        }
        catch(fs::filesystem_error const & e)
        {
            std::cerr << e.what() << std::endl;
        }
    }
    return true;
}
 
int main()
{
    fs::path directory_src("c:/Test"); // путь до копируемой директории
 
    fs::path directory_dest("c:/Testnew"); // путь до директории, в которую копируем
 
    boost::asio::io_service::work* pwork = new boost::asio::io_service::work(io); // чтобы boost::asio::io_service::run не завершалась даже при пустой очереди
    boost::thread_group tgroup; // пул потоков
    size_t tnum(4); // число потоков в пуле
    for(size_t i = 0; i < tnum; ++i) // наполнение пула
    {
        tgroup.create_thread(boost::bind(&boost::asio::io_service::run, &io));
    }
 
    copyDir(fs::path(directory_src), fs::path(directory_dest));
    delete pwork;
    tgroup.join_all();
    return 0;
}
5
Mellotron
0 / 0 / 0
Регистрация: 10.09.2012
Сообщений: 31
25.11.2012, 15:05  [ТС] #6
igorrr37, Огромное спасибо вам, про пулы не знал!
0
Mellotron
0 / 0 / 0
Регистрация: 10.09.2012
Сообщений: 31
01.12.2012, 22:39  [ТС] #7
Простите, а возник такой вопрос. Можно ли сделать так, чтобы поток создавался не для каждого копируемого файла, а для каждой директории? Попытался сделать, но из за еще скудных знаний С++ не смог.

Добавлено через 7 часов 14 минут
Будет ли так, если создавать потоки для итерации по директориям?
0
igorrr37
1867 / 1483 / 751
Регистрация: 21.12.2010
Сообщений: 2,473
Записей в блоге: 11
02.12.2012, 14:43 #8
Лучший ответ Сообщение было отмечено как решение

Решение

Создаётся отдельный поток для каждой директории. Весь вывод в консоль сделан через PrintMessage (синхронизация)
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
#include <iostream>
#include <memory>
#include <boost/filesystem.hpp>
#define BOOST_THREAD_USE_LIB
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/format.hpp>
#include <stdexcept>
#include <Windows.h>
namespace fs = boost::filesystem3;
 
boost::mutex mutex;
boost::asio::io_service io;
 
void PrintMessage(boost::format const& bf, std::ostream& ost)
{
    boost::lock_guard<boost::mutex> lg(mutex);
    ost << bf << std::endl;
    return;
}
 
void copy(fs::path const& source, fs::path const& destination)
{
    try
    {
        fs::copy(source, destination / source.filename());
        PrintMessage(boost::format("file %1% copied to %2% by %3% thread") % source.filename().string() % destination.string()
            % boost::this_thread::get_id(), std::cout);
    }
    catch(std::exception const& e)
    {
        PrintMessage(boost::format("Exception in copy %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
    }
}
 
void copyDir(fs::path const& source, fs::path const& destination)
{
    try
    {
        // Проверка правильности вызова функции
        if(!fs::exists(source) || !fs::is_directory(source))
        {
            throw std::runtime_error("Source directory " + source.string() +
                                     " does not exist or is not a directory.");
        }
        else if(fs::exists(destination))
        {
            throw std::runtime_error("Destination directory " + destination.string() +
                                    " already exists.");
        }
        // Создание директории
        else if(!fs::create_directory(destination))
        {
            throw std::runtime_error("Unable to create destination directory " +
                                    destination.string());
        }
 
    }
    catch(std::exception const& e)
    {
        PrintMessage(boost::format("Exception in copyDir %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
        return;
    }
    // Проверка содержимого директории
    for(fs::directory_iterator it(source); it != fs::directory_iterator(); ++it)
    {
        try
        {
            fs::path currentpath(it->path());
            if(fs::is_directory(currentpath))
            {
                // Рекурсия по нахождению директории
                boost::thread t(copyDir, currentpath, destination / currentpath.filename());
                PrintMessage(boost::format("%1% is scanning by %2% thread") % currentpath.string() % t.get_id(), std::cout);
                t.join();
            }
            else
            {
                io.post(boost::bind(copy, currentpath, destination)); // ставим copy в очередь пула
            }
        }
        catch(std::exception const& e)
        {
            PrintMessage(boost::format("Exception in copyDir %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
        }
    }
}
 
int main()
{
    SetConsoleOutputCP(1251);
    fs::path source("c:/Test"); // путь до копируемой директории
    fs::path destination("c:/Testnew"); // путь до директории, в которую копируем
    std::unique_ptr<boost::asio::io_service::work> pwork(new boost::asio::io_service::work(io)); // чтобы boost::asio::io_service::run не завершалась даже при пустой очереди
    boost::thread_group tgroup; // пул потоков
    unsigned tnum = boost::thread::hardware_concurrency(); // число потоков в пуле
    std::cout << "tnum: " << tnum << "\n\n";
    for(unsigned i = 0; i < tnum; ++i) // наполнение пула
    {
        tgroup.create_thread(boost::bind(&boost::asio::io_service::run, &io));
    }
    copyDir(source, destination);
    pwork.reset();
    tgroup.join_all();
    return 0;
}
Добавлено через 2 часа 11 минут
или так
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <memory>
#include <boost/filesystem.hpp>
#define BOOST_THREAD_USE_LIB
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/format.hpp>
#include <stdexcept>
#include <Windows.h>
namespace fs = boost::filesystem3;
 
boost::mutex mutex;
boost::asio::io_service io;
 
void PrintMessage(boost::format const& bf, std::ostream& ost)
{
    boost::lock_guard<boost::mutex> lg(mutex);
    ost << bf << std::endl;
    return;
}
 
void copy(fs::path const& source, fs::path const& destination)
{
    try
    {
        fs::copy(source, destination / source.filename());
        PrintMessage(boost::format("file %1% copied to %2% by %3% thread") % source.filename().string() % destination.string()
            % boost::this_thread::get_id(), std::cout);
    }
    catch(std::exception const& e)
    {
        PrintMessage(boost::format("Exception in ::copy %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
    }
}
 
void copyDir(fs::path const& source, fs::path const& destination)
{
    try
    {
        // Проверка правильности вызова функции
        if(!fs::exists(source) || !fs::is_directory(source))
        {
            throw std::runtime_error("Source directory " + source.string() +
                                     " does not exist or is not a directory.");
        }
        else if(fs::exists(destination))
        {
            throw std::runtime_error("Destination directory " + destination.string() +
                                    " already exists.");
        }
        // Создание директории
        else if(!fs::create_directory(destination))
        {
            throw std::runtime_error("Unable to create destination directory " +
                                    destination.string());
        }
 
    }
    catch(std::exception const& e)
    {
        PrintMessage(boost::format("Exception in copyDir %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
        return;
    }
    // Проверка содержимого директории
    for(fs::directory_iterator it(source); it != fs::directory_iterator(); ++it)
    {
        try
        {
            fs::path currentpath(it->path());
            if(fs::is_directory(currentpath))
            {
                // Рекурсия по нахождению директории
                io.post(boost::bind(copyDir, currentpath, destination / currentpath.filename()));
            }
            else
            {
                ::copy(currentpath, destination);
            }
        }
        catch(std::exception const& e)
        {
            PrintMessage(boost::format("Exception in copyDir %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
        }
    }
}
 
int main()
{
    SetConsoleOutputCP(1251);
    fs::path source("c:/Test"); // путь до копируемой директории
    fs::path destination("c:/Testnew"); // путь до директории, в которую копируем
    std::unique_ptr<boost::asio::io_service::work> pwork(new boost::asio::io_service::work(io)); // чтобы boost::asio::io_service::run не завершалась даже при пустой очереди
    boost::thread_group tgroup; // пул потоков
    unsigned tnum = boost::thread::hardware_concurrency(); // число потоков в пуле
    std::cout << "tnum: " << tnum << "\n\n";
    for(unsigned i = 0; i < tnum; ++i) // наполнение пула
    {
        tgroup.create_thread(boost::bind(&boost::asio::io_service::run, &io));
    }
    copyDir(source, destination);
    pwork.reset();
    tgroup.join_all();
    return 0;
}
5
Mellotron
0 / 0 / 0
Регистрация: 10.09.2012
Сообщений: 31
02.12.2012, 20:06  [ТС] #9
Получается, второй вариант создает столько потоков, сколько директорий?

Добавлено через 1 час 21 минуту
А нет, так будет получаться с таким кодом:

Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <memory>
#include <boost/filesystem.hpp>
#define BOOST_THREAD_USE_LIB
#include <boost/thread.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/format.hpp>
#include <stdexcept>
#include <Windows.h>
namespace fs = boost::filesystem3;
 
boost::mutex mutex;
boost::asio::io_service io;
 
void PrintMessage(boost::format const& bf, std::ostream& ost)
{
    boost::lock_guard<boost::mutex> lg(mutex);
    ost << bf << std::endl;
    return;
}
 
void copy(fs::path const& source, fs::path const& destination)
{
    try
    {
        fs::copy(source, destination / source.filename());
        PrintMessage(boost::format("file %1% copied to %2% by %3% thread") % source.filename().string() % destination.string()
            % boost::this_thread::get_id(), std::cout);
    }
    catch(std::exception const& e)
    {
        PrintMessage(boost::format("Exception in copy %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
    }
}
 
void copyDir(fs::path const& source, fs::path const& destination)
{
    try
    {
        // Проверка правильности вызова функции
        if(!fs::exists(source) || !fs::is_directory(source))
        {
            throw std::runtime_error("Source directory " + source.string() +
                                     " does not exist or is not a directory.");
        }
        else if(fs::exists(destination))
        {
            throw std::runtime_error("Destination directory " + destination.string() +
                                    " already exists.");
        }
        // Создание директории
        else if(!fs::create_directory(destination))
        {
            throw std::runtime_error("Unable to create destination directory " +
                                    destination.string());
        }
 
    }
    catch(std::exception const& e)
    {
        PrintMessage(boost::format("Exception in copyDir %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
        return;
    }
    // Проверка содержимого директории
    for(fs::directory_iterator it(source); it != fs::directory_iterator(); ++it)
    {
        try
        {
            fs::path currentpath(it->path());
            if(fs::is_directory(currentpath))
            {
                // Рекурсия по нахождению директории
                boost::thread t(copyDir, currentpath, destination / currentpath.filename());
                PrintMessage(boost::format("%1% is scanning by %2% thread") % currentpath.string() % t.get_id(), std::cout);
                t.join();
            }
            else
            {
                ::copy(currentpath, destination);
            }
        }
        catch(std::exception const& e)
        {
            PrintMessage(boost::format("Exception in copyDir %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
        }
    }
}
 
int main()
{
    SetConsoleOutputCP(1251);
    fs::path source("c:/Test"); // путь до копируемой директории
    fs::path destination("c:/Testnew"); // путь до директории, в которую копируем
    std::unique_ptr<boost::asio::io_service::work> pwork(new boost::asio::io_service::work(io)); // чтобы boost::asio::io_service::run не завершалась даже при пустой очереди
    boost::thread_group tgroup; // пул потоков
    unsigned tnum = boost::thread::hardware_concurrency(); // число потоков в пуле
    std::cout << "tnum: " << tnum << "\n\n";
    for(unsigned i = 0; i < tnum; ++i) // наполнение пула
    {
        tgroup.create_thread(boost::bind(&boost::asio::io_service::run, &io));
    }
    copyDir(source, destination);
    pwork.reset();
    tgroup.join_all();
    return 0;
}
0
igorrr37
1867 / 1483 / 751
Регистрация: 21.12.2010
Сообщений: 2,473
Записей в блоге: 11
03.12.2012, 16:04 #10
Цитата Сообщение от Mellotron Посмотреть сообщение
А нет, так будет получаться с таким кодом:
да, но там тред-родитель ждёт окончания треда-потомка через t.join().
В данном коде родитель и потомок работают параллельно
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
#include <iostream>
#include <boost/filesystem.hpp>
#define BOOST_THREAD_USE_LIB
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/format.hpp>
#include <stdexcept>
#include <Windows.h>
namespace fs = boost::filesystem;
 
boost::mutex mx; // синхронизация вывода в консоль
boost::condition_variable_any cvar;// синхронизация с потоком main()
boost::shared_mutex smx, smx1; // синхронизация с потоком main()
boost::thread_group tgroup;
 
void PrintMessage(boost::format const& bf, std::ostream& ost)
{
    boost::lock_guard<boost::mutex> lg(mx);
    ost << bf << std::endl;
    return;
}
 
void copy(fs::path const& source, fs::path const& destination)
{
    try
    {
        fs::copy(source, destination / source.filename());
        PrintMessage(boost::format("file %1% copied to %2% by %3% thread") % source.filename().string() % destination.string()
            % boost::this_thread::get_id(), std::cout);
    }
    catch(std::exception const& e)
    {
        PrintMessage(boost::format("Exception in ::copy %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
    }
}
 
void copyDir(fs::path const& source, fs::path const& destination)
{
    boost::shared_lock<boost::shared_mutex> slg(smx); // лочит smx чтобы main() тред не завершился
    cvar.notify_one(); // оповещает свой тред-родитель что smx залочен
    try
    {
        // Проверка правильности вызова функции
        if(!fs::exists(source) || !fs::is_directory(source))
        {
            throw std::runtime_error("Source directory " + source.string() +
                                     " does not exist or is not a directory");
        }
        else if(fs::exists(destination))
        {
            throw std::runtime_error("Destination directory " + destination.string() +
                                    " already exists");
        }
        // Создание директории
        else if(!fs::create_directory(destination))
        {
            throw std::runtime_error("Unable to create destination directory " +
                                    destination.string());
        }
 
    }
    catch(std::exception const& e)
    {
        PrintMessage(boost::format("Exception in copyDir %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
        return;
    }
    // Проверка содержимого директории
    for(fs::directory_iterator it(source); it != fs::directory_iterator(); ++it)
    {
        try
        {
            fs::path currentpath(it->path());
            if(fs::is_directory(currentpath))
            {
                tgroup.create_thread(boost::bind(copyDir, currentpath, destination / currentpath.filename()));
                boost::shared_lock<boost::shared_mutex> sl(smx1);
                cvar.wait(sl);// ждёт оповещения от потока-потомка что smx залочен
            }
            else
            {
                ::copy(currentpath, destination);
            }
        }
        catch(std::exception const& e)
        {
            PrintMessage(boost::format("Exception in copyDir %1% thread: %2%") % boost::this_thread::get_id() % e.what(), std::cerr);
        }
    }
}
 
int main()
{
    SetConsoleOutputCP(1251);
    fs::path source("c:/Test"); // путь до копируемой директории
    fs::path destination("c:/Testnew"); // путь до директории, в которую копируе
    tgroup.create_thread(boost::bind(copyDir, source, destination));
    boost::shared_lock<boost::shared_mutex> sl(smx1);
    cvar.wait(sl);// ждёт оповещения от потока-потомка что smx залочен
    while(!smx.try_lock()); // пытается получить эксклюзивное владение smx
    std::cout << "tgroup.size(): " << tgroup.size() << std::endl;
    return 0;
}
2
03.12.2012, 16:04
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.12.2012, 16:04

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

вернуть вывод программы в терминал, или в файл
есть программа mlnet, которая стартует при загрузке оси скриптом из init.d при...

Настройка syslog - будет ли параллельно вывод в терминал и консоль?
Здравствуйте! Возник следующий вопрос: Если к примеру настроить на...


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

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru