반응형

pthread의 pthread_create 함수에서 람다(lambda)를 사용한 예제입니다.

람다를 사용하면 따로 함수를 선언하지 않고 코드 내에 람다를 정의한 후, pthread_create에서 바로 사용할 수 있습니다.

주의할 점은 람다 함수에서 지역변수만 접근 가능합니다.



윈도우의 경우 pthread를 Visual Studio에서 사용하려면 다음 포스트를 참고하세요.


Visual Studio 2019에서 pthread 사용하는 방법

https://webnautes.tistory.com/1452 




2021. 01. 16  최초작성

2021. 01. 28  최종작성




= 는 값 전달이고 &는 참조 전달이라고 하는데 테스트해본 결과는 좀 다른 듯합니다. =를 사용하면 지정한 변수만 값을 변경할 수 있고  &를 사용하면 따로 변수 지정을 하지 않아도 모든 로컬 변수의 값을 변경할 수 있습니다. 



람다 함수에서 =를 사용하면 


#ifdef _MSC_VER
#define HAVE_STRUCT_TIMESPEC
#endif
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

template <typename Fx> void* start_routine_t(void* arg)
{
Fx* f = (Fx*)arg;
return (*f)();
}

int main(int argc, char* argv[])
{
pthread_t threads;

int x = 1;
int y = 2;
int sum = 0;

auto add = [=, &sum]()    // 지정한 sum만 값 변경 가능
{
x = 5;
y = 6;
sum = x + y;
return nullptr;
};

pthread_create(&threads, nullptr,
start_routine_t<decltype(add)>, &add);

pthread_join(threads, nullptr);
printf("%d + %d = %d\n", x, y, sum);

return 0;
}



다음처럼 에러가 납니다. 



Ubuntu


webnautes@webnautes-pc:~$ g++ -o test test.cpp -lpthread

test.cpp: In lambda function:

test.cpp:24:7: error: assignment of read-only variable ‘x’

   x = 5;

       ^

test.cpp:25:7: error: assignment of read-only variable ‘y’

   y = 6;



Visual Studio 2019


Build started...

1>------ Build started: Project: pthread example, Configuration: Debug x64 ------

1>main.cpp

1>C:\Users\webnautes\source\repos\pthread example\pthread example\main.cpp(24,3): error C3491: 'x': a by copy capture cannot be modified in a non-mutable lambda

1>C:\Users\webnautes\source\repos\pthread example\pthread example\main.cpp(25,3): error C3491: 'y': a by copy capture cannot be modified in a non-mutable lambda

1>Done building project "pthread example.vcxproj" -- FAILED.

========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========




에러나는 변수 수정하는 부분을 주석처리하면 문제가 해결됩니다. 


#ifdef _MSC_VER
#define HAVE_STRUCT_TIMESPEC
#endif
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

template <typename Fx> void* start_routine_t(void* arg)
{
Fx* f = (Fx*)arg;
return (*f)();
}

int main(int argc, char* argv[])
{
pthread_t threads;

int x = 1;
int y = 2;
int sum = 0;

auto add = [=, &sum]()    // 지정한 sum만 값 변경 가능
{
// x = 5;
// y = 6;
sum = x + y;
return nullptr;
};

pthread_create(&threads, nullptr,
start_routine_t<decltype(add)>, &add);

pthread_join(threads, nullptr);
printf("%d + %d = %d\n", x, y, sum);

return 0;
}



webnautes@webnautes-pc:~$ ./test

1 + 2 = 3




람다 함수에서 &를 사용하면 따로 변수를 지정하지 않아도 모든 지역변수에 접근가능합니다. 


#ifdef _MSC_VER
#define HAVE_STRUCT_TIMESPEC
#endif
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

template <typename Fx> void* start_routine_t(void* arg)
{
Fx* f = (Fx*)arg;
return (*f)();
}

int main(int argc, char* argv[])
{
pthread_t threads;

int x = 1;
int y = 2;
int sum = 0;

auto add = [&]()        // &로 바꾸면 변수를 지정하지 않아도 모든 변수 변경 가능
{
            x = 5;
            y = 6;
sum = x + y;
return nullptr;
};

pthread_create(&threads, nullptr,
start_routine_t<decltype(add)>, &add);

pthread_join(threads, nullptr);
printf("%d + %d = %d\n", x, y, sum);

return 0;
}


webnautes@webnautes-pc:~$ ./test

5 + 6 = 11


람다 함수에 전달되는 아규먼트가 변하는 경우에 유의할 점은 전달받은 후, 로컬 변수에 대입해놓아야 하는 점입니다. 


#ifdef _MSC_VER
#define HAVE_STRUCT_TIMESPEC
#include <windows.h> //for Sleep
#else
#include <unistd.h> // for sleep
#endif
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>


template <typename Fx> void* start_routine_t(void* arg)
{
Fx* f = (Fx*)arg;
return (*f)();
}

const char* list[] = { "00000", "11111", "22222" };

int main(int argc, char* argv[])
{
pthread_t threads;

for (int i = 0; i < 3; i++)
{
auto add = [=, &i]()
{
// 지역변수에 대입하여 사용하지 않으면 변수값 변화가 반영되어
// 문제된다.
int k = i;
const char* c = list[k];

while (1)
{
printf("[%d] %s\n", k, c);
}

return nullptr;
};

pthread_create(&threads, nullptr,
start_routine_t<decltype(add)>, &add);
#ifdef _MSC_VER
      Sleep(5); // 스레드 함수의 지역 변수에 대입될 시간을 준다.
#else
            sleep(5);
#endif
}

while (1);

return 0;
}




참고


https://programmer.help/blogs/c-binds-lambda-expressions-to-callback-functions.html


반응형

문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.

도움이 되셨다면 토스아이디로 후원해주세요.
https://toss.me/momo2024


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts