Skip to content

Conversation

@ITHelpDec
Copy link

@ITHelpDec ITHelpDec commented Apr 26, 2023

Code tweaked to allow compilation.

Subjective amendments included in an attempt to make code more robust and declarative.

Please consider writing fuller-bodied code samples to provide more context to the reader, as well as ensure the code compiles and runs as intended.

Please also consider (if reasonable) more liberal use of whitespace to improve legibility at first read.

I have provided an example of my understanding of the code sample below - please feel free to amend as appropriate.

Listing 4.22 (click to expand / collapse)
#include <future>
#include <vector>
#include <iostream>
#include <numeric>

int process_chunk(std::vector<int>::const_iterator b, std::vector<int>::const_iterator e) {
    return std::accumulate(b, e, 0);
}

template <typename ForwardIt>
int process_chunk_template(ForwardIt b, ForwardIt e) {
    return std::accumulate(b, e, 0);
}

int gather_results(const std::vector<int> &ivec) {
    return std::accumulate(ivec.begin(), ivec.end(), 0);
}

std::future<int> process_data(const std::vector<int> &ivec) {
    const std::size_t chunk_size = ivec.size() / 4;
    std::size_t remaining_size, this_chunk_size;
    
    std::vector<std::future<int>> results;
    
    for (auto it = ivec.begin(); it != ivec.end(); /*...*/) {
        std::size_t remaining_size = std::distance(it, ivec.end());
        std::size_t this_chunk_size = std::min(remaining_size, chunk_size);
        
        // standard function
        results.push_back(std::async(process_chunk, it, it + this_chunk_size));
        
        // function templates
        
        // - explicit specialisation
        // results.push_back(std::async(process_chunk_template<std::vector<int>::const_iterator>, it, it + this_chunk_size));
        
        // - decltype shorthand
        // results.push_back(std::async(process_chunk_template<decltype(it)>, it, it + this_chunk_size));
        
        // - lambda shorthand
        // results.push_back(std::async([=] () {
        //     return process_chunk_template(it, it + this_chunk_size);
        // }));
        
        it += this_chunk_size;
    }
    
    return std::async([all_results = std::move(results)] () mutable {
        std::vector<int> v;
        v.reserve(all_results.size());
        
        for (auto &fut : all_results) { v.push_back(fut.get()); }
        
        return gather_results(v);
    });
}

int main()
{
    std::vector<int> ivec = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    
    auto fut = process_data(ivec);
    
    std::cout << "fut.get(): " << fut.get() << '\n';
    
    return 0;
}

Thank you for your contributions.

v.push_back(f.get());
- - -
'this' argument to member function 'get' has type 'const std::future<int>', but function is not marked const
consider just using `it`, as `begin + this_chunk_size` isn't technically the beginning anymore
it seems expensive to repeatedly initialise std::size_t variables inside of the loop when they could be initialised once, then modified as and when
we do not amend `vec` during the function - we therefore run the risk of losing out on potential compiler optimisations by ignoring this constness
current function pointer structure will not translate well into using template functions
ITHelpDec added a commit to ITHelpDec/ccia_code_samples that referenced this pull request Apr 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant