1

for example, use pthread_create create two threads, and both of them print "hello world", and my question is how to count how many times "hello world" printed by each thread?

zie tan ny
  • 71
  • 4

2 Answers2

3

and my question is how to count how many times "hello world" printed by each thread?

The easy way to do it would be to declare a global atomic counter at the top of your file:

static std::atomic<int> counter = 0;

and then have each thread increment the counter (i.e. ++counter) each time it prints "hello world". Then in your main(), after all of the threads have been joined, you can print out the value counter.

Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
1

I can show you the code that child thread pass variable to the main thread;

void * thread_func(void *arg)
{
    int num = 10; //assume 'num' is the times that child thread  printed "hello world"
    pthread_exit((void *)num);
}

int main()
{
    pthread_t thread;
    void * tret;
    pthread_create(&thread,NULL,thread_func,NULL);
    pthread_join(thread,&tret);
    printf("%d\n",(int)tret);  
    return 0;
}
charlie
  • 267
  • 1
  • 3
  • 15
  • pthread_exit((void *)num); - this seems problematic, in that it's casting an int to a pointer, and even if it was doing the correct thing, and returning (void *)&num, it'd be returning a pointer to a local variable, which is invalid after the function returns. – Mark Bessey Nov 19 '15 at 03:42
  • ....yes,there is a problem with the type of `num` .The type of `num` should be `long`,but other code is correct.You should return `(void *)num` ,not `(void *)&num`.if you return `(void *)&num`,this will return a porinter to a local variable. – charlie Nov 19 '15 at 03:53
  • Could use `std::intptr_t` or `std::uintptr_t` (but I'd trust it to work just fine as is). Can just `return (void*)num;` too BTW / using `pthread_exit` is optional and extra porting effort if you move off pthreads to e.g. `std::thread` et al. – Tony Delroy Nov 19 '15 at 04:03
  • Regardless of the integer type, casting from an arbitrary integer to a void* is bad form, because it's not portable. On some platform, merely doing that cast with certain integer values will cause undefined behavior. – Mark Bessey Nov 19 '15 at 04:03
  • @MarkBessey: any reference to support that concern? – Tony Delroy Nov 19 '15 at 04:04
  • It's hard to find links to the ISO standards online, but relevant excerpts are in this SO question: http://stackoverflow.com/questions/7822904/is-it-always-safe-to-convert-an-integer-value-to-void-and-back-again-in-posix Note especially that any void * is guaranteed to be convertible to an intptr_t and back, but that arbitrary intptr_t values may not necessarily be safe to convert to void* – Mark Bessey Nov 19 '15 at 04:08
  • @MarkBessey: 5.2/5 seems to contradict you, as I understand it: *A value of integral type or enumeration type can be explicitly converted to a pointer. A pointer converted to an integer of sufficient size (if any such exists on the implementation) and back to the same pointer type will have its original value; **mappings between pointers and integers are otherwise implementation-defined.*** Note that *implementation-defined* is not *undefined*, and implementations do tend to yield the original value for `int`->`void*`->`int`. – Tony Delroy Nov 19 '15 at 04:12
  • Note too that *"A value of integral type or enumeration type can be explicitly converted to a pointer."* is explicitly allowed, and only aspects of the mapping are implementation defined, so *"not necessarily safe"* seems untrue, though you're right that it's not portably correct numerically. – Tony Delroy Nov 19 '15 at 04:15
  • Yeah, bad wording on my part. It's implementation-defined, not undefined, but implementation-defined can cover a whole variety of behaviors, from "it just works", to "casting any integer to pointer whose bit pattern is not a valid pointer will cause an invalid address trap exception". See "trap representations", here: http://www.ibm.com/developerworks/library/pa-ctypes3/ – Mark Bessey Nov 23 '15 at 20:25