Skip to content

Instantly share code, notes, and snippets.

@willeccles
Last active October 27, 2016 02:36
Show Gist options
  • Save willeccles/5af17f1b1ae02a20ede6ddd2b5b9afc0 to your computer and use it in GitHub Desktop.
Save willeccles/5af17f1b1ae02a20ede6ddd2b5b9afc0 to your computer and use it in GitHub Desktop.
how to thread

Threading

So, you want to learn about std::thread added in C++11? This will include that and a small bit on lambdas, which were also added.

How to make two things happen at once:

note: all code samples assume that <thread>, <iostream>, and (later) <future> have been included.

// both threads will run this
void printThreadNum(int num) {
	// this will print the number of the thread that launched it
	std::cout << num << std::cout;
}

int main(void) {
	// create two threads, each running printThreadNum()
	std::thread t1(printThreadNum, 1); // printThreadNum is the thing to run, 1 is the input
	std::thread t2(printThreadNum, 2);
	// both of those threads have just started running, without you telling them to start manually
	
	// join the threads back to the main thread (if they have a long-running task, this will wait till the thread is done before returning)
	
	t1.join(); // once t1 is done executing, it will cease to exist basically
	t2.join(); // same here
	
	return 0;
}

Now, that was a simple example, but we could do the same thing with a lambda repeated twice (which, in this case, saves time). I won’t get into that too much, but instead of the method created, we would replace printThreadNum in the threads with [] (int num) { std::cout << num << std::cout; }. Just something to keep in mind.

Threads returning things:

Say we have a method that returns an integer. We want to capture this after the thread joins. However, we can’t do that unless the thread can return something, but how can it do that? Here we have to use the std::future and std::promise. Basically, the promise stores a value, and then the future is a placeholder for the value outside that thread. Look at this example:

// the promise is where we will store the output
void myNum(std::promise<int> && p, int input) {
	// we will just return the input.
	p.set_value(input);
	std::cout << "Returned " << input << "!" << std::endl;
}

int main(void) {
	// these will store the output
	std::promise<int> outputPromise;
	std::future<int> outputFuture;
	
	// tell the future to wait for the promise's output
	outputFuture = outputPromise.get_future();
	
	// std::move tells the thread to use that promise as the input, basically
	std::thread myThread(myNum, std::move(outputPromise), 42);
	
	// so now the thread has started, we wait for it to finish…
	myThread.join();
	
	// now we store the value returned, which should be 42
	int returned = outputFuture.get();
	
	// now we can print it
	std::cout << returned << std::cout;
	
	return 0;
}

As you can see, it’s a little more complicated to return a value, but it’s not that bad.

One more thing:

Let’s say we want to get input from the user (using argv) which is how many threads to make. This is more difficult, but really not that bad, assuming that each one does the same thing.

void printThreadNum(int num) {
	std::cout << num << std::cout;
}

int main(int argc, char* argv[]) {
	// in this case, we will just assume that the user made input 1 (since argv[0] is the name of the executable) a number, so no error handling
	int threadNum = atoi(argv[1]); // atoi requires <cstdlib>
	
	// now we want to make threadNum threads. we have to store them in this array:
	std::thread* threads = new std::thread[threadNum];
	
	// now we can start each one, making them all print their own numbers:
	for (int i = 0; i < threadNum; i++) {
		threads[i] = std::thread(printThreadNum, i);
	}
	
	// now we wait for all of them:
	for (int i = 0; i < threadNum; i++) {
		threads[i].join();
	}
	
	// now they should all have printed their respective numbers nearly simultaneously (keep in mind, std::cout isn't too threadsafe so it might look funny. If this is the case, include <cstdio> and use printf() and similar.
	
	return 0;
}

Multiple that return stuff:

Say I want to do the same as above but returning things too. All I have to do is make an array of promises and futures and then do the same as the threads, only with them. I’ll just add the code needed in main() and you can figure out where it should go.

// inside main, before the loop where we set each thread in *threads: (replace int with whatever)
std::promise *promises = new std::promise<int>[numThreads];
std::future *futures = new std::future<int>[numThreads];

for (int i = 0; i < numThreads; i++) {
	futures[i] = promises[i].get_future();
}

// this goes after the threads have all been joined:
int *returns = new int[numThreads]; // store all values here

for (int i = 0; i < numThreads; i++) {
	// you could also join threads[i] right here and then get() after it, but this would obviously have to replace the joining loop we made before.
	returns[i] = futures[i].get();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment