+ 1

Doubt on Functor when used with thread

Hi Please find below code: https://sololearn.com/compiler-playground/c1BF2l1hn7Fg/?ref=app Why output is 200 and not 300? Does this mean thread object created calls overloaded operator() ? Why passing an object of functor class to thread function calls overloaded () operator? Any reason of this ? If it calls , then why function taking class object does not call overloaded () operator ? Additional query : why it result into compile time error when function signature takes object as call by value rather than call by reference?

11th Feb 2024, 6:03 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
17 Answers
+ 3
☝️ I hope my changes to the code will help you better understand how it works. Run it a dozen times to see how it works. You can also play with it by commenting out one line and documenting another line similar to it accordingly...😎: https://sololearn.com/compiler-playground/ch96kv6FnzAn/?ref=app
13th Feb 2024, 2:03 AM
Solo
Solo - avatar
+ 2
For a better understanding of the code, I have deleted everything superfluous and unnecessary. The number of times you use the object, the number of times the loop works out. In your case, twice, and in mine once: class App { public: void operator()() { for(int i=0;i<100;++i) { ++cnt; } } int get() {return cnt;} private: int cnt = 0; }; int main() { App obj; thread t1(ref(obj)); t1.join(); cout << obj.get(); return 0; }
11th Feb 2024, 7:32 PM
Solo
Solo - avatar
+ 2
Ketan Lalcheta threads are executed. functors passed to them using std::ref are called, and the state of the object is updated. Here is another example, but this one accepts an int argument. your example is the same, only your functor don't accept any argument. But the process is the same. Maybe you are mixing up constructors and functors? You instantiated your class in main. You passed your functors by ref to the threads. https://sololearn.com/compiler-playground/cHVXZWdWODWJ/?ref=app
12th Feb 2024, 11:48 PM
Bob_Li
Bob_Li - avatar
+ 2
So I'm back and ready to provide my explanations... Apparently, you are just getting acquainted with the work of Thread. I'm not a professional either, I'm just learning, so let's figure it out together. This code demonstrates the execution of asynchronous, multithreaded operations. This is necessary, for example, to simultaneously (conditionally) control two different characters in the game. At first glance, this code should split the execution of the loop into two threads, which is why I tried to get from you why you decided that the output should be 300, I would most likely think that 100 because the loop will be executed only once, although the call operator will be called twice, because this is how this construction works. That is, we must assume that if we want to write code for 200 million iterations, then we can write a cycle twice as small as necessary and create two threads, or, respectively, a 4 times smaller cycle and create 4 threads. 👇
13th Feb 2024, 1:55 AM
Solo
Solo - avatar
+ 1
Ketan Lalcheta you have to add obj(); after instantiating App obj; in main, if you expect 300. you only ran 2 threads. you did not run it in main. I do not understand the purpose of testFunc. Perhaps you mean: void testFunc(App& obj) { obj(); } This will also give you 300.
12th Feb 2024, 12:07 AM
Bob_Li
Bob_Li - avatar
+ 1
Ketan Lalcheta it seems it does call the () operator. void operator()() { cout<<"functor called!\n"; for(int i=0;i<100;++i) { m.lock(); ++cnt; m.unlock(); } }
12th Feb 2024, 10:02 AM
Bob_Li
Bob_Li - avatar
+ 1
Why so.. I got confused about this behavior
12th Feb 2024, 10:25 AM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 1
maybe executing the thread is the same as calling obj()? The same thing happens even without using thread. App obj; auto r = ref(obj); r(); //x+=100 r(); //x+=100
12th Feb 2024, 10:42 AM
Bob_Li
Bob_Li - avatar
+ 1
If it gets called when ref is passed , then why not getting called for free function taking class object as reference?
12th Feb 2024, 2:16 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
+ 1
Ketan Lalcheta I'm sorry, but I have to run. I'll explain later.
12th Feb 2024, 2:20 PM
Solo
Solo - avatar
+ 1
Solo instead of class based functors, the same thing can be done with functions and external variables. I modified your code to test how it could be done. Instead of modifying an internal variable, we could modify an external variable instead. https://sololearn.com/compiler-playground/cnkOpqcXpETo/?ref=app
13th Feb 2024, 3:11 PM
Bob_Li
Bob_Li - avatar
+ 1
Bob_Li Yes, there is a wide range for creativity here, as this is a new level of development in programming. And he still has to study and study. For example, if you test this code, it turns out that it is much slower than if you did it using a regular loop, you need to at least achieve full synchronization of threads...😎
13th Feb 2024, 7:42 PM
Solo
Solo - avatar
0
Let's forget about testFunc() for time being and ignore it for a time being. Still why output is 200? We are not calling functor 2 times. Right? We just passed reference of functor class object to thread object. Does it call overloaded operator()? Is function call using object and passing reference of object a same thing?
12th Feb 2024, 8:57 AM
Ketan Lalcheta
Ketan Lalcheta - avatar
0
Ketan Lalcheta I don't understand anything. Explain it to me, stupid in Russian. Why do you think the output should be 300? In my opinion, everything is very clear...🤔
12th Feb 2024, 1:26 PM
Solo
Solo - avatar
0
Write below line in overloaded operator () funcitons: cout << "operator()\n"; Why it gets called ?
12th Feb 2024, 1:46 PM
Ketan Lalcheta
Ketan Lalcheta - avatar
0
Ketan Lalcheta Well, how else? Of course, it is called, therefore it is called the "call operator", and accordingly this object is a functor or literally a "Function Object" because it uses it in its constructor, and not an ordinary function.
12th Feb 2024, 2:11 PM
Solo
Solo - avatar
0
I agree that it is call operator. But does it mean that it gets called even through object is passed as reference?
12th Feb 2024, 2:15 PM
Ketan Lalcheta
Ketan Lalcheta - avatar