Using Global array in multhreaded application - c++

I am using Toradex Colibri iMX7 for running our embedded software(C,C++). Our application is to acquire data from two sensors and to plot it in real time.We are having two threads, one for data acquisition(append data in a global array) and other thread for plotting the array of values(same global array) in a interval of time(100ms). While trying this our application gets crashed after some time. I know some kind of thread synchronization is necessary but don't know exactly how to handle this. Any suggestions or examples would be helpful.

Here is a dummy example how to use mutex for thread synchronization with pthread library.
#include <pthread.h>
pthread_mutex_t _mutex;
int globalArray[5];
void Write()
{
pthread_mutex_lock (&_mutex);
// Write to global array
globalArray[0] = 0;
pthread_mutex_unlock (&_mutex);
}
int Read( )
{
int i;
pthread_mutex_lock (&_mutex);
// read from global array
i = globalArra[0];
pthread_mutex_unlock (&_mutex);
return i;
}
Before you start using mutex object one time initialization needed. eg. begining of your program.
pthread_mutex_init(&_mutex, NULL);
and when no longer need it you need to destroy it. eg. before program ends.
pthread_mutex_destroy(&_mutex);

Related

Multithreading & shared resource: Periodically copy data from buffer (data structure) to a file using C++

My code has a data structure say for example "vector of vecor of Strings. I've 2 threads:
THread 1 is writing data to this data structure (buffer in RAM).
Thread 2 running in parallel which should copy data FROM the above buffer i.e data structure TO a file for every "x" miliseconds.
I'm wondering how would I achieve this in C++ ? It should consider key
points in problem statement like:
a) The copy from buffer to file should happen only once in "X"
miliseconds.
b) Synchronization between both threads.
EDITING THE QUERY WITH MORE DETAILS PER THE ASK
I want to build a library (*.lib) & this library exposes some APIs hence it gets input data from EXE or any entity which uses my library through these APIs.
Say the data received by my library is in the form of a vector of strings.
FillLibraryDataStructure(std::vector<std::string>); // is the API of this library. Any app can call this API & pass a vector of string to this library.
Example app code:
for(int i=100; i<100;i))
{
std::vector<std::string> vec = GetVectorOfString(); // GetVectorOfString from business logic
FillLibraryDataStructure(vec);
}
Library code havin a shared resource:
// Within library I've a 2D vector i.e. vector of vector of
strings where all the vector of strings passed by application to this librray are added as a new row in vecofvecofstr.
SHARED RESOURCE:
std::vector<std::vector<string>> vecofvecofstr;
THREAD 1: is copying the data it receives from API to the data structure i.e. vector of vector of strings.
vecofvecofstr.push_back(vec);
THREAD 2: is copying the contents of this vector of vector of string (which was written to in 1st thread ) to files (XML, HTML etc..)
for every "X" miiliseconds.
Few more points about thread1: 1) Thread 1 should be running
continuously i.e. as and when application calls the API the data
received should be put to the data structure vecofvecofstr. 2) After
"X" miliseonds of copying the data to the buffer, 2nd thread should
get started & it should copy all the stuff that was dumped to buffer
till date. Again after "X" milisonds the thread 2 should pause & wait
for "X" ms.
How do I achieve this. Here the 1st thread is the default one in which my library code would be running.
How do i achieve this using C++?
You could use std::mutex and std::condition_variable> to your advantage. And a double buffer would keep locking to a minimum.
std::condition_variable> is the nearest thing to an event the std has to offer, its use is a bit contrived, but it works.
The example below uses a double buffer so you can keep on buffering data while thread 2 is saving to file, without locking.
The std:condition_variable is used so your application can exit without waiting. This is only needed if you want your application to exit promptly, else you can use a timer. The call to notify_all() will prevent the wait_for() from timing out, and wake the writing thread immediately, so it can exit without waiting for the timeout to occur. See ref at :http://en.cppreference.com/w/cpp/thread/condition_variable
Header:
#include <mutex>
// a generic double buffer
template<typename _Data>
class DoubleBuffer
{
private:
std::mutex mutex_;
std::vector<std::vector<_Data>> storeBuffer_;
std::vector<std::vector<_Data>> saveBuffer_;
public:
void lock() { mutex_.lock(); }
void unlock() { mutex_.unlock();}
auto& GetStoreBuffer() { return storeBuffer_; }
auto& GetSaveBuffer() { return saveBuffer_; }
auto& Swap()
{
std::lock_guard<std::mutex> lock(mutex_);
std::swap(storeBuffer_, saveBuffer_);
}
};
In your library:
#include <condition_variable>
#include <thread>
#include <chrono>
#include <mutex>
#include <vector>
#include <string>
// As an example, could be inside a class, or struct
static std::condition_variable exiting;
static std::mutex lk_exiting;
static DoubleBuffer<std::string> yourBuffer;
void FillLibraryDataStructure(std::vector<std::string> strings)
{
// the lock is only for the duration of a swap - very short at worst.
std::lock_guard<DoubleBuffer<std::string>> lock(yourBuffer);
yourBuffer.GetStoreBuffer().emplace_back(strings);
}
void StoreLoop()
{
for(;;)
{
{ // wait_for() unlocks lk_exiting, doc says lock should
// be set before cv is triggered.
std::unique_lock<std::mutex> lk_exiting;
if (std::cv_status::no_timeout == exiting.wait_for(lk_exiting, 60s))
break; // app is exiting
}
yourBuffer.Swap();
auto& stringsToSave = GetSaveBuffer();
// save... You do have plenty of time.
}
}
// as an example. A destructor would be a good place for this
void Exit_Application()
{
// stops the wait_for operation in StoreLoop()
exiting.notify_all();
}
As a general answer regard to your general question, there is two possible options:
1- use some wait, signal commands to sleep and wake threads in parallel
2- use some sleep to provide X milliseconds in reading thread
If you need better answer, give more details

Producer-consumer based multi-threading for image processing

UPDATE: I have provided the reason of problem and its solution in my answer below.
I want to implement multi-threading which is based upon Producer-consumer approach for an image processing task. For my case, the Producer thread should grabs the images and put them into a container whereas the consumer thread should extract the images from the Container thread. I think that I should use queue for the implementation of container.
I want to use the following code as suggested in this SO answer. But I have become quite confused with the implementation of container and putting the incoming image into it in the Producer thread.
PROBLEM: The image displayed by the first consumer thread does not contain the full data. And, the second consumer thread never displays any image. May be, there is some race situation or lock situation due to which the second thread is not able to access the data of queue at all. I have already tried to use Mutex.
#include <vector>
#include <thread>
#include <memory>
#include <queue>
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
Mutex mu;
struct ThreadSafeContainer
{
queue<unsigned char*> safeContainer;
};
struct Producer
{
Producer(std::shared_ptr<ThreadSafeContainer> c) : container(c)
{
}
void run()
{
while(true)
{
// grab image from camera
// store image in container
Mat image(400, 400, CV_8UC3, Scalar(10, 100,180) );
unsigned char *pt_src = image.data;
mu.lock();
container->safeContainer.push(pt_src);
mu.unlock();
}
}
std::shared_ptr<ThreadSafeContainer> container;
};
struct Consumer
{
Consumer(std::shared_ptr<ThreadSafeContainer> c) : container(c)
{
}
~Consumer()
{
}
void run()
{
while(true)
{
// read next image from container
mu.lock();
if (!container->safeContainer.empty())
{
unsigned char *ptr_consumer_Image;
ptr_consumer_Image = container->safeContainer.front(); //The front of the queue contain the pointer to the image data
container->safeContainer.pop();
Mat image(400, 400, CV_8UC3);
image.data = ptr_consumer_Image;
imshow("consumer image", image);
waitKey(33);
}
mu.unlock();
}
}
std::shared_ptr<ThreadSafeContainer> container;
};
int main()
{
//Pointer object to the class containing a "container" which will help "Producer" and "Consumer" to put and take images
auto ptrObject_container = make_shared<ThreadSafeContainer>();
//Pointer object to the Producer...intialize the "container" variable of "Struct Producer" with the above created common "container"
auto ptrObject_producer = make_shared<Producer>(ptrObject_container);
//FIRST Pointer object to the Consumer...intialize the "container" variable of "Struct Consumer" with the above created common "container"
auto first_ptrObject_consumer = make_shared<Consumer>(ptrObject_container);
//SECOND Pointer object to the Consumer...intialize the "container" variable of "Struct Consumer" with the above created common "container"
auto second_ptrObject_consumer = make_shared<Consumer>(ptrObject_container);
//RUN producer thread
thread producerThread(&Producer::run, ptrObject_producer);
//RUN first thread of Consumer
thread first_consumerThread(&Consumer::run, first_ptrObject_consumer);
//RUN second thread of Consumer
thread second_consumerThread(&Consumer::run, second_ptrObject_consumer);
//JOIN all threads
producerThread.join();
first_consumerThread.join();
second_consumerThread.join();
return 0;
}
I don't see an actual question in your original question, so I'll give you the reference material I used to implement producer-consumer in my college course.
http://cs360.byu.edu/static/lectures/winter-2014/semaphores.pdf
Slides 13 and 17 give good examples of producer-consumer
I made use of this in the lab which I have posted on my github here:
https://github.com/qzcx/Internet_Programming/tree/master/ThreadedMessageServer
If you look in my server.cc you can see my implementation of the producer-consumer pattern.
Remember that using this pattern that you can't switch the order of the wait statements or else you can end up in deadlock.
Hope this is helpful.
EDIT:
Okay, so here is a summary of the consumer-producer pattern in my code linked above. The idea behind the producer consumer is to have a thread safe way of passing tasks from a "producer" thread to "consumer" worker threads. In the case of my example, the work to be done is to handle client requests. The producer thread (.serve()) monitors the incoming socket and passes the connection to consumer threads (.handle()) to handle the actual request as they come in. All of the code for this pattern is found in the server.cc file (with some declarations/imports in server.h).
For the sake of being brief, I am leaving out some detail. Be sure to go through each line and understand what is going on. Look up the library functions I am using and what the parameters mean. I'm giving you a lot of help here, but there is still plenty of work for you to do to gain a full understanding.
PRODUCER:
Like I mentioned above, the entire producer thread is found in the .serve() function. It does the following things
Initializes the semaphores. There are two version here because of OS differences. I programmed on a OS X, but had to turn in code on Linux. Since Semaphores are tied to the OS, it is important to understand how to use semaphores in your particular setup.
It sets up the socket for the client to talk to. Not important for your application.
Creates the consumer threads.
Watches the client socket and uses the producer pattern to pass items to the consumers. This code is below
At the bottom of the .serve() function you can see the following code:
while ((client = accept(server_,(struct sockaddr *)&client_addr,&clientlen)) > 0) {
sem_wait(clients_.e); //buffer check
sem_wait(clients_.s);
clients_.q->push(client);
sem_post(clients_.s);
sem_post(clients_.n); //produce
}
First, you check the buffer semaphore "e" to ensure there is room in your queue to place the request. Second, acquire the semaphore "s" for the queue. Then add your task (In this case, a client connection) to the queue. Release the semaphore for the queue. Finally, signal to the consumers using semaphore "n".
Consumer:
In the .handle() method you really only care about the very beginning of the thread.
while(1){
sem_wait(clients_.n); //consume
sem_wait(clients_.s);
client = clients_.q->front();
clients_.q->pop();
sem_post(clients_.s);
sem_post(clients_.e); //buffer free
//Handles the client requests until they disconnect.
}
The consumer does similar actions to the producer, but in opposite fashion. First the consumer waits for the producer to signal on the semaphore "n". Remember since there are multiple consumers it is completely random which consumer might end up acquiring this semaphore. They fight over it, but only one can move passed this point per sem_post of that semaphore. Second, they acquire the queue semaphore like the producer does. Pop the first item off the queue and release the semaphore. Finally, they signal on the buffer semaphore "e" that there is now more room in the buffer.
Disclaimer:
I know the semaphores have terrible names. They match my professor's slides since that's where I learned it. I think they stand for the following:
e for empty : this semaphore stops the producer from pushing more items on the queue if it is full.
s for semaphore : My least favorite. But my professor's style was to have a struct for each shared data struct. In this case "clients_" is the struct including all three semaphores and the queue. Basically this semaphore is there to ensure no two threads touch the same data structure at the same time.
n for number of items in the queue.
Ok, so to make it as simple as possible. You will need 2 threads, mutex, queue and 2 thread processing functions.
Header.h
static DWORD WINAPI ThreadFunc_Prod(LPVOID lpParam);
static DWORD WINAPI ThreadFunc_Con(LPVOID lpParam);
HANDLE m_hThread[2];
queue<int> m_Q;
mutex m_M;
Add all needed stuff, these are just core parts you need
Source.cpp
DWORD dwThreadId;
m_hThread[0] = CreateThread(NULL, 0, this->ThreadFunc_Prod, this, 0, &dwThreadId);
// same for 2nd thread
DWORD WINAPI Server::ThreadFunc_Prod(LPVOID lpParam)
{
cYourClass* o = (cYourClass*) lpParam;
int nData2Q = GetData(); // this is whatever you use to get your data
m_M.lock();
m_Q.push(nData2Q);
m_M.unlock();
}
DWORD WINAPI Server::ThreadFunc_Con(LPVOID lpParam)
{
cYourClass* o = (cYourClass*) lpParam;
int res;
m_M.lock();
if (m_Q.empty())
{
// bad, no data, escape or wait or whatever, don't block context
}
else
{
res = m_Q.front();
m_Q.pop();
}
m_M.unlock();
// do you magic with res here
}
And in the end of main - don't forget to use WaitForMultipleObjects
All possible examples can be found directly in MSDN so there is quite nice commentary about that.
PART2:
ok, so I believe header is self-explainable, so I will give you little bit more description to source. Somewhere in your source (can be even in Constructor) you create threads - the way how to create thread may differ but idea is the same (in win - thread is run right after its creation in posix u have to join). I believe u shall have somewhere a function which starts all your magic, lets call it MagicKicker()
In case of posix, create thread in constructor and join em in your MagicKicker(), win - create in MagicKicker()
Than you would need to declare (in header) two function where you thread function will be implemented ThreadFunc_Prod and ThreadFunc_Prod , important magic here is that you will pass reference to your object to this function (coz thread are basically static) so u can easy access shared resources as queues, mutexes, etc...
These function are actually doing the work. You actually have all u need in you code, just use this as adding routine in Producer:
int nData2Q = GetData(); // this is whatever you use to get your data
m_M.lock(); // locks mutex so nobody cant enter mutex
m_Q.push(nData2Q); // puts data from producer to share queue
m_M.unlock(); // unlock mutex so u can access mutex in your consumer
And add this to your consumer:
int res;
m_M.lock(); // locks mutex so u cant access anything wrapped by mutex in producer
if (m_Q.empty()) // check if there is something in queue
{
// nothing in you queue yet OR already
// skip this thread run, you can i.e. sleep for some time to build queue
Sleep(100);
continue; // in case of while wrap
return; // in case that u r running some framework with threadloop
}
else // there is actually something
{
res = m_Q.front(); // get oldest element of queue
m_Q.pop(); // delete this element from queue
}
m_M.unlock(); // unlock mutex so producer can add new items to queue
// do you magic with res here
The problem mentioned in my question was that the image displayed by the Consumer thread was not containing complete data. The image displayed by the Consumer thread contains several patches which suggest that it could not get the full data produced by Producer thread.
ANSWER The reason behind it is the declaration of Mat image inside the while loop of Consumer thread. The Mat instance created inside the while loop gets deleted once the second round of while loop starts and therefore the Producer thread was never able to access the data of Mat image created in the Consumer thread.
SOLUTION: I should have done it something like this
struct ThreadSafeContainer
{
queue<Mat> safeContainer;
};
struct Producer
{
Producer(std::shared_ptr<ThreadSafeContainer> c) : container(c)
{
}
void run()
{
while(true)
{
// grab image from camera
// store image in container
Mat image(400, 400, CV_8UC3, Scalar(10, 100,180) );
mu.lock();
container->safeContainer.push(Mat);
mu.unlock();
}
}
std::shared_ptr<ThreadSafeContainer> container;
};
struct Consumer
{
Consumer(std::shared_ptr<ThreadSafeContainer> c) : container(c)
{
}
~Consumer()
{
}
void run()
{
while(true)
{
// read next image from container
mu.lock();
if (!container->safeContainer.empty())
{
Mat image= container->safeContainer.front(); //The front of the queue contain the image
container->safeContainer.pop();
imshow("consumer image", image);
waitKey(33);
}
mu.unlock();
}
}
std::shared_ptr<ThreadSafeContainer> container;
};

pthread - accessing multiple objects with a thread

I'm trying to get my hands on multi threading and it's not working so far. I'm creating a program which allows serial communication with a device and it's working quite well without multi threading. Now I want to introduce threads, one thread to continuously send packets, one thread to receive and process packets and another thread for a GUI.
The first two threads need access to four classes in total, but using pthread_create() I can only pass one argument. I then stumled upon a post here on stack overflow (pthread function from a class) where Jeremy Friesner presents a very elegant way. I then figured that it's easiest to create a Core class which contains all the objects my threads need access to as well as all functions for the threads.So here's a sample from my class Core:
/** CORE.CPP **/
#include "SerialConnection.h" // Clas for creating a serial connection using termios
#include "PacketGenerator.h" // Allows to create packets to be transfered
#include <pthread.h>
#define NUM_THREADS 4
class Core{
private:
SerialConnection serial; // One of the objects my threads need access to
pthread_t threads[NUM_THREADS];
pthread_t = _thread;
public:
Core();
~Core();
void launch_threads(); // Supposed to launch all threads
static void *thread_send(void *arg); // See the linked post above
void thread_send_function(); // See the linked post above
};
Core::Core(){
// Open serial connection
serial.open_connection();
}
Core::~Core(){
// Close serial connection
serial.close_connection();
}
void Core::launch_threads(){
pthread_create(&threads[0], NULL, thread_send, this);
cout << "CORE: Killing threads" << endl;
pthread_exit(NULL);
}
void *Core::thread_send(void *arg){
cout << "THREAD_SEND launched" << endl;
((Core *)arg)->thread_send_function();
return NULL;
}
void Core::thread_send_function(){
generator.create_hello_packet();
generator.send_packet(serial);
pthread_exit(NULL);
}
Problem is now that my serial object crashes with segmentation fault (that pointer stuff going on in Core::thread_send(void *arg) makes me suspicious. Even when it does not crash, no data is transmitted over the serial connection even though the program executed without any errors. Execution form main:
/** MAIN.CPP (extract) VARIANT 1 **/
int main(){
Core core;
core.launch_threads(); // No data is transferred
}
However, if I call the thread_send_function directly (the one the thread is supposed to execute), the data is transmitted over the serial connection flawlessly:
/** MAIN.CPP (extract) VARIANT 1 **/
int main(){
Core core;
core.thread_send_function(); // Data transfer works
}
Now I'm wondering what the proper way of dealing with this situation is. Instead of that trickery in Core.cpp, should I just create a struct holding pointers to the different classes I need and then pass that struct to the pthread_create() function? What is the best solution for this problem in general?
The problem you have is that your main thread exits the moment it created the other thread, at which point the Core object is destroyed and the program then exits completely. This happens while your newly created thread tries to use the Core object and send data; you either see absolutely nothing happening (if the program exits before the thread ever gets to do anything) or a crash (if Core is destroyed while the thread tries to use it). In theory you could also see it working correctly, but because the thread probably takes a bit to create the packet and send it, that's unlikely.
You need to use pthread_join to block the main thread just before quitting, until the thread is done and has exited.
And anyway, you should be using C++11's thread support or at least Boost's. That would let you get rid of the low-level mess you have with the pointers.

(C++ Threads): Creating worker threads that will be listening to jobs and executing them concurrently when wanted

Suppose we have two workers. Each worker has an id of 0 and 1. Also suppose that we have jobs arriving all the time, each job has also an identifier 0 or 1 which specifies which worker will have to do this job.
I would like to create 2 threads that are initially locked, and then when two jobs arrive, unlock them, each of them does their job and then lock them again until other jobs arrive.
I have the following code:
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
struct job{
thread jobThread;
mutex jobMutex;
};
job jobs[2];
void executeJob(int worker){
while(true){
jobs[worker].jobMutex.lock();
//do some job
}
}
void initialize(){
int i;
for(i=0;i<2;i++){
jobs[i].jobThread = thread(executeJob, i);
}
}
int main(void){
//initialization
initialize();
int buffer[2];
int bufferSize = 0;
while(true){
//jobs arrive here constantly,
//once the buffer becomes full,
//we unlock the threads(workers) and they start working
bufferSize = 2;
if(bufferSize == 2){
for(int i = 0; i<2; i++){
jobs[i].jobMutex.unlock();
}
}
break;
}
}
I started using std::thread a few days ago and I'm not sure why but Visual Studio gives me an error saying abort() has been called. I believe there's something missing however due to my ignorance I can't figure out what.
I would expect this piece of code to actually
Initialize the two threads and then lock them
Inside the main function unlock the two threads, the two threads will do their job(in this case nothing) and then they will become locked again.
But it gives me an error instead. What am I doing wrong?
Thank you in advance!
For this purpose you can use boost's threadpool class.
It's efficient and well tested. opensource library instead of you writing newly and stabilizing it.
http://threadpool.sourceforge.net/
main()
{
pool tp(2); //number of worker threads-currently its 2.
// Add some tasks to the pool.
tp.schedule(&first_task);
tp.schedule(&second_task);
}
void first_task()
{
...
}
void second_task()
{
...
}
Note:
Suggestion for your example:
You don't need to have individual mutex object for each thread. Single mutex object lock itself will does the synchronization between all the threads. You are locking mutex of one thread in executejob function and without unlocking another thread is calling lock with different mutex object leading to deadlock or undefined behaviour.
Also since you are calling mutex.lock() inside whileloop without unlocking , same thread is trying to lock itself with same mutex object infinately leading to undefined behaviour.
If you donot need to execute threads parallel you can have one global mutex object can be used inside executejob function to lock and unlock.
mutex m;
void executeJob(int worker)
{
m.lock();
//do some job
m.unlock();
}
If you want to execute job parallel use boost threadpool as I suggested earlier.
In general you can write an algorithm similar to the following. It works with pthreads. I'm sure it would work with c++ threads as well.
create threads and make them wait on a condition variable, e.g. work_exists.
When work arrives you notify all threads that are waiting on that condition variable. Then in the main thread you start waiting on another condition variable work_done
Upon receiving work_exists notification, worker threads wake up, and grab their assigned work from jobs[worker], they execute it, they send a notification on work_done variable, and then go back to waiting on the work_exists condition variable
When main thread receives work_done notification it checks if all threads are done. If not, it keeps waiting till the notification from last-finishing thread arrives.
From cppreference's page on std::mutex::unlock:
The mutex must be unlocked by all threads that have successfully locked it before being destroyed. Otherwise, the behavior is undefined.
Your approach of having one thread unlock a mutex on behalf of another thread is incorrect.
The behavior you're attempting would normally be done using std::condition_variable. There are examples if you look at the links to the member functions.

Multithreading using pthread in C++ with shared variables

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;
}
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.
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.