Reputation:
This pulls in a text file properly but it does not output it in the correct order, I need one thread to yield but when i try to implement it, it has not worked. Every time the program runs it displays the vows and cons in a random order, even with the yield function in place.
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <stdlib.h>
#include <thread>
#include <vector>
using namespace std;
void cons(string c){
//Prints consanants
cout <<"CONS: " << c << endl;
this_thread::yield();
}
void vow(string v){
//Prints vowels
// allowing other ready threads to run
this_thread::yield();
cout <<"VOW: " << v << endl;
}
int main() {
//Creates an array of 100
string words[100];
//Creates a starting point for i
int i = 0;
//string called x
string s;
//Takes in a file
ifstream inFile;
//Creates a vector of threads to print
vector <thread> PrintingThreads;
//Opens up the text file "phrase.txt"
inFile.open("phrase.txt");
//If It is not able to open the file
if (!inFile) {
//Display error message
cout << "Unable to open specified file";
//Exit with an error(1)
exit(1);
}
while (inFile >> s) {
words[i]=s;
i++;
}
//cycle
for (int l=0; l<i; l++)
{
char first (words[l][0]);
if ((first == 'a') || (first == 'e') || (first == 'i') || (first == 'o') || (first == 'u')||(first == 'A') || (first == 'E') || (first == 'I') || (first == 'O') || (first == 'U'))
{
/
PrintingThreads.push_back(thread(vow,words[l]));
}
else
{
PrintingThreads.push_back(thread(cons,words[l]));
}
}// loop with a range variable
for (thread& t: PrintingThreads)
t.join();
inFile.close();
}
Upvotes: 1
Views: 583
Reputation: 69977
There are three problems:
You can't use this_thread::yield
to determine the execution order of threads, because calling it in one particular thread, while suggesting that priority be given to other threads, does not guarantee that the execution won't return to the current thread until all other threads have finished. According to the Standard (§30.3.2/2), it merely offers the implementation the opportunity to reschedule, but it is left up to thread-scheduling mechanisms at run-time to decide whether or not to reschedule at all, and when exactly to return to the current thread.
So the following may happen when a line starting with a vowel is encountered: a) It starts a vowel-processing thread, b) Execution immediately switches to that thread and processes the yield
command, c) The implementation is given an opportunity to reschedule the thread so it switches back to the main thread, d) The main thread processes another line which may be a vowel-line again, e) A new thread is created for the new line, f) The yield
command is applied and the implementation reschedules the execution and switches to another thread, g) The implementation chooses the still unfinished vowel-thread of the first line and therefore prints that vowel, finishing that thread, h) The implementation then switches back to the second vowel-thread and finishes that too (still before any consonant is encountered), and so on.
That is just one possible order in which things may happen. It may as well happen that the second vowel finishes before the first, or that they both wait until a consonant-thread is started and finished before the two vowel-threads. The order is not determined by yield
.
Even if using yield
was guaranteed to wait until all other currently running threads have completed (which it isn't!), there would be two problems: a) At the time a vowel-thread is executed, any future consonant-threads don't exist yet because you create the threads one after the other, so the vowel-thread wouldn't have anything to wait for, b) On the other hand, the only other thread that is guaranteed to exist when a vowel-thread is started is the main thread; but if the vowel-thread had to wait until even the main thread is finished, it would have to wait forever, because the main thread includes a join
command at the end which forces it to wait for the vowel-thread. Both threads would wait for each other in eternal deadlock.
At the end of the main program, you execute join
commands in the order in which the threads were inserted into the vector. So even if we were to assume that yield
causes a thread to wait until another thread uses join
to wait for that thread (which is completely wrong an assumption anyway), it still wouldn't work because the consonant-threads include a yield
statement as well, so any vowel-thread being joined would have to wait for consonant-threads that follow it (in the original order of the strings) to finish, which they wouldn't because their join
command wouldn't have been called yet.
If you want to guarantee the output to alternate between vowels and consonants (or, alternatively, to print all consonant lines followed by all vowel lines), the most straight-forward way is to do away with threads and simply put the incoming lines into two arrays (or vectors), one for vowel lines and one for consonant lines. At the end you can then easily determine the printing order, and it wouldn't consume more memory than it does already (given that you store all lines in the words
array).
Upvotes: 2