1
votes

I am trying to create 2 threads, that work with float arrays. Howere compiler gives me these errors:

/usr/include/c++/9/thread: In instantiation of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(bool*, float*, float*, float*); _Args = {bool*, float (*)[10], float (*)[10], float (*)[10]}; <template-parameter-1-3> = void]’:
main.cpp:16:66:   required from here
/usr/include/c++/9/thread:120:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
  120 |           typename decay<_Args>::type...>::value,
      |                                            ^~~~~
/usr/include/c++/9/thread: In instantiation of ‘struct std::thread::_Invoker<std::tuple<void (*)(bool*, float*, float*, float*), bool*, float (*)[10], float (*)[10], float (*)[10]> >’:
/usr/include/c++/9/thread:131:22:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(bool*, float*, float*, float*); _Args = {bool*, float (*)[10], float (*)[10], float (*)[10]}; <template-parameter-1-3> = void]’
main.cpp:16:66:   required from here
/usr/include/c++/9/thread:243:4: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<void (*)(bool*, float*, float*, float*), bool*, float (*)[10], float (*)[10], float (*)[10]> >::__result<std::tuple<void (*)(bool*, float*, float*, float*), bool*, float (*)[10], float (*)[10], float (*)[10]> >’
  243 |    _M_invoke(_Index_tuple<_Ind...>)
      |    ^~~~~~~~~
/usr/include/c++/9/thread:247:2: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<void (*)(bool*, float*, float*, float*), bool*, float (*)[10], float (*)[10], float (*)[10]> >::__result<std::tuple<void (*)(bool*, float*, float*, float*), bool*, float (*)[10], float (*)[10], float (*)[10]> >’
  247 |  operator()()
      |  ^~~~~~~~
/usr/include/c++/9/thread: In instantiation of ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(float*); _Args = {float (*)[10]}; <template-parameter-1-3> = void]’:
main.cpp:17:43:   required from here
/usr/include/c++/9/thread:120:44: error: static assertion failed: std::thread arguments must be invocable after conversion to rvalues
  120 |           typename decay<_Args>::type...>::value,
      |                                            ^~~~~
/usr/include/c++/9/thread: In instantiation of ‘struct std::thread::_Invoker<std::tuple<void (*)(float*), float (*)[10]> >’:
/usr/include/c++/9/thread:131:22:   required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(float*); _Args = {float (*)[10]}; <template-parameter-1-3> = void]’
main.cpp:17:43:   required from here
/usr/include/c++/9/thread:243:4: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<void (*)(float*), float (*)[10]> >::__result<std::tuple<void (*)(float*), float (*)[10]> >’
  243 |    _M_invoke(_Index_tuple<_Ind...>)
      |    ^~~~~~~~~
/usr/include/c++/9/thread:247:2: error: no type named ‘type’ in ‘struct std::thread::_Invoker<std::tuple<void (*)(float*), float (*)[10]> >::__result<std::tuple<void (*)(float*), float (*)[10]> >’
  247 |  operator()()
      |  ^~~~~~~~

I thought that I forgot some ctor arguments for the dma thread but that is not the case. Here is my code:

#include <iostream>
#include <cstdint>
#include <thread>

void dma_service(bool*, float*, float*, float*);
void live_audio(float*);
void live_draw(float*);


    
    constexpr int d_size = 10;
    float data[d_size];
    float pwm_cp[d_size];
    float fft_cp[d_size];
    bool drdy = 0;
    std::thread dma_thrd(dma_service, &drdy, &data, &pwm_cp, &fft_cp);
    std::thread audio_thrd(live_draw, &pwm_cp);


int main(){
    for (auto i = 0; i < d_size; i++)
    {
        data[i] = 0;
        pwm_cp[i] = 0;
    }
    printf("Hello, World!\n");
    drdy = 1;

    int k = 3;
    while(k-->0)
    {
        audio_thrd.join();
        printf("\n\n\n");
        
        for (auto i = 0; i < d_size; i++)
        {
            data[i]++;
        }
        drdy = 1;
    }

}

void dma_service(bool* flag, float* d_array, float* pwm_array, float* fft_array) {
    while (!flag) ;

    for (auto i = 0; i < d_size; i++)
    {
        pwm_array[i] = d_array[i];
        fft_array[i] = d_array[i];
    }

    flag = 0;

}

void live_audio(float* pwm_array) {
    dma_thrd.join();
    printf("Audio Array:\n");
    for (auto i = 0; i < d_size; i++)
    {
        printf("PWM_CP[%d] %f\n", i, pwm_array[i]);
    }
}

I don't have much experience with lambda functions so I have no idea if they're needed here (and would be happy to avoid them). Thanks for any suggestions!

2
&data[0], &pwm_cp[0], &fft_cp[0]? to have float* instead of float (*)[10]Jarod42
audio_thrd.join(); in a loop is suspicious.Jarod42
You are potentially starting your threads before main, passing pointers to uninitialized arrays. There is no visible synchronization between threads. As a consequence you have multiple data races, each cause your program to have Undefined Behavior. Multithreading is a very hard facet of programming that can't be practically learned by trial and error.François Andrieux
You are taking pointers to arrays. Arrays already decay to pointers to their first element automatically. Instead of std::thread f(function, &arg); you would simply write std::thread f(function, arg); where arg is an array and function expects a pointer to an array. Remove the & operator.François Andrieux
How do I declare them outside of main and then run them in main? I need to have global acces to them.nero

2 Answers

3
votes

Given float data[d_size];, &data is deduced as a "pointer to array" type. That won't match a float* argument.

You can simply omit &, then array-to-pointer decay will kick in and the types will match.

std::thread dma_thrd(dma_service, &drdy, data, pwm_cp, fft_cp);
std::thread audio_thrd(live_draw, pwm_cp);

Or pass the address of the first element:

std::thread dma_thrd(dma_service, &drdy, &data[0], &pwm_cp[0], &fft_cp[0]);
std::thread audio_thrd(live_draw, &pwm_cp[0]);

Note that this is not sufficient to make the program work. I see it's lacking thread synchronization, and starting threads at global scope like that is problematic because they will start before main(). Also join() in a loop won't work correctly, as join() can be performed only once.

1
votes

To have matching arguments, you need:

constexpr int d_size = 10;
float data[d_size];
float pwm_cp[d_size];
float fft_cp[d_size];
bool drdy = 0;

void dma_service(bool*, float*, float*, float*);
std::thread dma_thrd(dma_service, &drdy, &data[0], &pwm_cp[0], &fft_cp[0]);

Demo

or

constexpr int d_size = 10;
float data[d_size];
float pwm_cp[d_size];
float fft_cp[d_size];
bool drdy = 0;

void dma_service(bool*, float(*)[10], float(*)[10], float(*)[10]);
std::thread dma_thrd(dma_service, &drdy, &data, &pwm_cp, &fft_cp);