Reputation: 1176
I'm new to threading (and C/C++ for that matter), and I'm attempting to use multiple threads to access shared variables.
In the main, I've created a variable char inputarray[100];
Thread 1: This thread will be reading data from stdin in 2 byte bursts, and appending them to the inputarray. (input by feeding a file in)
Thread 2: This thread will be reading data 1 byte at a time, performing a calculation, and putting its data into an output array.
Thread 3: This thread will be outputting data from the output array in 2 byte bursts. (stdout)
I've attempted the input part and got it working by passing a struct, but would like to do it without using a struct, but it has been giving me problems.
If I can get input down, I'm sure I'll be able to use a similar strategy to complete output. Any help would be greatly appreciated.
Below is a rough template for the input thread.
#include <stdio.h>
#include <pthread.h>
using namespace std;
void* input(void* arg) {
char reading[3];
fread(reading,1,2,stdin);
//append to char inputarray[]..???
}
int main() {
char inputarray[100];
pthread_t t1;
pthread_create(&t1, NULL, &input, &inputarray);
void *result;
pthread_join(t1,&result);
return 0;
}
Upvotes: 1
Views: 3960
Reputation: 264381
You are on the correct track:
As a note the pthreads libraries are C libs so you need to declare the callbacks as C functions:
extern "C" void* input(void* arg);
Personally I would pass the address of the first element:
pthread_create(&t1, NULL, &input, &inputarray[0]);
This then makes your code look like this:
void* input(void* arg) {
try
{
char* inputarray = (char*)arg;
size_t inputLocation = 0;
// Need to make sure you don't over run the buffer etc...
while(!finished())
{
fread(&inputarray[inputLocation],1,2,stdin);
inputLocation += 2;
}
}
catch(...){} // Must not let exceptions escape a thread.
return NULL;
}
The trouble with this style is that you are putting the responsibility for coordination into each individual thread. The writer thread has to check for end the reader thread has to check there is data available etc. All this needs coordination so now you need some shared mutexes and condition variables.
A better choice is to move that responsibility into the object the does the communication. So I would create a class that has the basic operations needed for communication then make its methods do the appropriate checks.
class Buffer
{
public:
void write(......); //
void read(.....); //
private:
// All the synchronization and make sure the two threads
// behave nicely inside the object.
};
int main()
{
pthread_t threads[3];
std::pair<Buffer, Buffer> comms;
// comms.first inputToRead
// comms.second processesToOutput
pthread_create(&threads[0], NULL, &readInput, &comms.first); // Input
pthread_create(&threads[1], NULL, &procInput, &comms); // Processing
pthread_create(&threads[2], NULL, &genOutput, &comms.second); // Output
void *result;
pthread_join(threads[0],&result);
pthread_join(threads[1],&result);
pthread_join(threads[2],&result);
}
As a side note:
Unless there is something very strange about your processing of data. This would probably be faster written as a single threaded application.
Upvotes: 2
Reputation: 9706
Several issues:
I think array on stack is very bad choice for shared variable, because it has a fixed size and it's not clear from Thread 2 and 3 where to put new elements or where to read elements from. I would propose to use std::vector
or std::deque
instead.
Initially your container is empty. Then Thread 2 pushes some elements to it.
Thread 3 is polling (or waiting on condition variable) container, and once it found new elements - print them
You have to synchronize access to shared variable with mutex (consider pthread mutex, std::mutex
or boost::mutex
). You might also want to use condition variable to notify Thread 3 about new elements in the queue. But for initial implementation it's not needed.
Do you really have to use pthread primitives? Normally it's much easier and safer (i.e. exception safety) to use std::thread
, std::mutex
(if you have modern compiler), or boost::thread
, boost::mutex
otherwise.
Upvotes: 8