// windows_procon.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include <windows.h>
#include <process.h>
using namespace std;
HANDLE mutex;
HANDLE emptySlots;
HANDLE filledSlots;
#define BUFFER_SIZE 10
void *producer(void *);
void *consumer(void *);
int produceItem(void);
void printBuffer(void);
int buffer[BUFFER_SIZE];
int head = 0;
int tail = 0;
int _tmain(int argc, _TCHAR* argv[])
{
DWORD prodThrdID, consThrdID;
mutex = CreateMutex(NULL,FALSE,NULL);
emptySlots = CreateSemaphore(NULL,BUFFER_SIZE,BUFFER_SIZE,NULL);
filledSlots = CreateSemaphore(NULL,0,0,NULL);
srand(time(NULL));
_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void*))producer,
0, 0, (unsigned int *)&prodThrdID);
_beginthreadex(NULL, 0, (unsigned int(__stdcall *)(void*))consumer,
0, 0, (unsigned int *)&consThrdID);
return 0;
}
void *producer(void *n)
{
int item;
for(int i = 0; i <BUFFER_SIZE+5; i++)
{
WaitForSingleObject(emptySlots,INFINITE);
WaitForSingleObject(mutex,INFINITE);
item = produceItem();
//printf("Producing");
cout << "Producing: " << item << endl;
//logfile << "Producing: "<< item << endl;
//fprintf(logfile, "Producing: %d \n", item);
buffer[head] = item;
head = (head + 1) % BUFFER_SIZE;
printBuffer();
ReleaseMutex(mutex);
ReleaseSemaphore(filledSlots,1, NULL);
}
return n;
}
void *consumer(void *n)
{
for(int i = 0; i <BUFFER_SIZE+5; i++)
{
WaitForSingleObject(filledSlots,INFINITE);
//Sleep(500);
WaitForSingleObject(mutex,INFINITE);
cout << "Consuming: " << buffer[tail] << endl;
buffer[tail] = 0;
tail = (tail + 1) % BUFFER_SIZE;
printBuffer();
ReleaseMutex(mutex);
ReleaseSemaphore(emptySlots,1, NULL);
}
return n;
}
int produceItem(void)
{
int x = (rand()%11 + 1);
return x;
}
void printBuffer(void)
{
for(int i = 0; i <BUFFER_SIZE; i++)
{
printf("%d ", buffer[i]);
}
printf("END \n");
}
My program here is supposed to be an algorithm for the producer-consumer problem. I think I have the algorithm correct my only problem is that I'm having trouble getting the threads to run properly. Can someone tell me what the issue is?
You need to wait for the threads you create with _beginthreadex to do their work, as it stands you program will exit immediately after creating them. I haven't looked any further at you logic.
Here is an example.
hThread = (HANDLE)_beginthreadex( NULL, 0, &SecondThreadFunc, NULL, 0, &threadID );
WaitForSingleObject( hThread, INFINITE );
Related
I use ftd3xx.dll to communicate with the device
The data read part and the data write part are divided into threads and used.
#include <thread>
#include <queue>
#include <array>
#include <windows.h>
using namespace std;
bool dataRead = false;
CRITICAL_SECTION sec;
queue< vector<unsigned short>> BufferQueue;
unsigned WINAPI Write(void* arg) {
int Width = 1000;
vector<unsigned short> data;
data.reserve(Width);
while (Opened)
{
while (dataRead)
{
if (BufferQueue.size() > 0) {
EnterCriticalSection(&sec);
data = BufferQueue.front();
BufferQueue.pop();
LeaveCriticalSection(&sec);
}
else
{
this_thread::sleep_for(2ms);
continue;
}
//wrtie something
}
if (!dataRead)
break;
}
_endthreadex(0);
return 0;
}
unsigned WINAPI Read(void* arg) {
int Width = 1000;
vector<unsigned short> data(Width);
BYTE* acReadBuf = new BYTE[Width];
ULONG ulBytesRead = 0;
int idx = 0;
Sleep(100);
while (dataRead)
{
ftStatus = FT_ReadPipe(ftHandle, CstReadPipeNo, acReadBuf, Width, &ulBytesRead, NULL);
if (FT_SUCCESS(ftStatus))
{
idx = 0;
for (int i = 0; i < Width; i++) {
data[i] = ((unsigned short)((unsigned short)acReadBuf[idx] | ((unsigned short)acReadBuf[idx + 1] << 8)));
idx += 2;
}
EnterCriticalSection(&sec);
if (BufferQueue.size() > 10000) {
queue< vector<unsigned short>> empty;
swap(BufferQueue, empty);
}
BufferQueue.push(data);
LeaveCriticalSection(&sec);
}
else
{
}
}
_endthreadex(0);
return 0;
}
void main() {
//start
InitializeCriticalSection(&sec);
dataRead = true;
HANDLE r_hThread = NULL;
unsigned r_threadID;
r_hThread = (HANDLE)_beginthreadex(NULL, 0, Read, NULL, 0, &r_threadID);
HANDLE w_hThread = NULL;
unsigned w_threadID;
w_hThread = (HANDLE)_beginthreadex(NULL, 0, Write, NULL, 0, &w_threadID);
//....///
//stop
dataRead = false;;
WaitForSingleObject(r_hThread, INFINITE);
WaitForSingleObject(w_hThread, INFINITE);
DeleteCriticalSection(&sec);
}
I want to queue the array directly, but first I am using it as a vector.
Importantly, data loss occurs when other programs are run or even calculators are run.
The same is true even if the device gives the data late or fast.
I would be grateful if someone could help me.
#include <iostream>
#include <queue>
#include <thread>
#include <process.h>
#include <windows.h>
#include <stdlib.h>
int g_Width = 100;
std::queue<std::vector<unsigned short>> BufferQueue;
bool dataRead = false;
unsigned short* g_pImgBuf = NULL;
unsigned int _stdcall Write(void* arg) {
std::vector<unsigned short> data;
data.reserve(g_Width);
int line = 0;
while (dataRead)
{
if (!dataRead)
break;
for (int i = 0; i < g_Width; i++) {
data.push_back(i);
}
BufferQueue.push(data);
data.clear();
}
_endthreadex(0);
return 0;
}
unsigned int _stdcall Read(void* arg) {
std::vector<unsigned short> data;
data.reserve(g_Width);
unsigned short color = 0;
int line = 0;
while (dataRead)
{
g_pImgBuf = new unsigned short[g_Width];
if (!BufferQueue.empty()) {
data = BufferQueue.front();
BufferQueue.pop();
}
else if (!dataRead)
break;
else {
continue;
}
for (int j = 0; j < g_Width; j++) {
color = data[j];
color += 2;
g_pImgBuf[j] = color;
}
data.clear();
}
if (g_pImgBuf) { free(g_pImgBuf); g_pImgBuf = NULL; }
_endthreadex(0);
return 0;
}
int main()
{
dataRead = true;
HANDLE r_hThread = NULL;
unsigned r_threadID;
r_hThread = (HANDLE)_beginthreadex(NULL, 0, Read, NULL, 0, &r_threadID);
HANDLE w_hThread = NULL;
unsigned w_threadID;
w_hThread = (HANDLE)_beginthreadex(NULL, 0, Write, NULL, 0, &w_threadID);
while (true)
{
Sleep(100);
}
}
The following error occurred
vector subscript out of range 1501 error
In the middle of the thread function
Give it sleep (2) and it works sometimes but soon I get an error.
If the vector is the problem, is there any other way to store the array in the queue?
I don't know where the problem is
Is there a good way?
You simply cannot do this in such a simplistic way. If you want one thread to pick messages off the queue that are being written by another thread you need mtuexes and condition variables. This is not a trivial task. I suggest a lot of googling. I will look too and updat here if I find a good link
https://juanchopanzacpp.wordpress.com/2013/02/26/concurrent-queue-c11/
https://gist.github.com/ictlyh/f8473ad0cb1008c6b32c41f3dea98ef5
I have a problem with my code. It works, but I cannot avoid using global semaphores. I have 3 thread functions. the first is run by 10 threads. The second and third are run by 2 threads each. These threads should run without having race conditions. In addition, they should communicate with each other. I use a user defined queue class for communications between threads and between the threads and main. Also, I use the semaphores to achieve mutual exclusion between the threads. Since I declare the instance of the queue class and the semaphores in a global manner, I do not have to pass them to any function. They are accessible to any function in this program. However, this is not a healthy way to write programs. Therefore, I ask you, how to declare the queue and the semaphores locally, and what is the best way to pass them between threads.
// queueString header
#include <string>
#include <queue>
#include <semaphore.h>
using namespace std;
class queueString
{
public:
queueString();
~queueString();
void qPush(string str);
string qPop();
private:
sem_t queueSem;
queue <string> q;
};
//queueString class
#include "queueString.h"
using namespace std;
// queue class that will enqueue and dequeue atomically.
queueString::queueString(){
sem_init(&queueSem, 0, 1);
}
queueString::~queueString(){}
void queueString::qPush(string str){
sem_wait(&queueSem);
this->q.push(str);
sem_post(&queueSem);
}
string queueString::qPop(){
sem_wait(&queueSem);
string str = this->q.front();
q.pop();
sem_post(&queueSem);
return str;
}
//The three threads with main
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <iostream>
#include "queueString.h"
using namespace std;
//My question is here, How to declare the variables below locally, and where
// is the right place to declare them, and how to pass them to threads?
sem_t s12, s13, s21, s31, sthr1, sthr2[2], sthr3[2], printSem;
sem_t idInitializationSemMainToThread, idInitializationSemThreadToMain;
queueString q = queueString();
#define THR1NUM 10
#define THR2NUM 2
#define THR3NUM 2
void printString(string str);
void *thread1(void* arg){
sem_wait(&idInitializationSemMainToThread);
int *pnum = (int *)arg;
int thr_1_ID = *pnum;
sem_post(&idInitializationSemThreadToMain);
sem_wait(&sthr1);
string value= "THR1 ";
value.append(to_string(thr_1_ID));
q.qPush(value);
sem_post(&s12);
sem_wait(&s21);
value= "2nd Iteration THR1 ";
value.append(to_string(thr_1_ID));
q.qPush(value);
sem_post(&s13);
sem_wait(&s31);
sem_post(&sthr1);
}
void *thread2(void* arg){
sem_wait(&idInitializationSemMainToThread);
int *pnum = (int *)arg;
int thr_2_ID = *pnum;
sem_post(&idInitializationSemThreadToMain);
while (true)
{
sem_wait(&sthr2[thr_2_ID]);
sem_wait(&s12);
string readVal = q.qPop();
printString(readVal + ", THR2 "+ to_string(thr_2_ID));
if (thr_2_ID==0)
sem_post(&sthr2[1]);
else
sem_post(&sthr2[0]);
sem_post(&s21);
}
}
void *thread3(void* arg){
sem_wait(&idInitializationSemMainToThread);
int *pnum = (int *)arg;
int thr_3_ID = *pnum;
sem_post(&idInitializationSemThreadToMain);
while (true)
{
sem_wait(&sthr3[thr_3_ID]);
sem_wait(&s13);
string readVal = q.qPop();
printString(readVal + " THR3 " + to_string(thr_3_ID));
if (thr_3_ID == 0)
sem_post(&sthr3[1]);
else
sem_post(&sthr3[0]);
sem_post(&s31);
}
}
int main(){
pthread_t thr1[THR1NUM], thr2[THR2NUM], thr3[THR3NUM];
sem_init(&s12, 0, 0);
sem_init(&s13, 0, 0);
sem_init(&s31, 0, 0);
sem_init(&s21, 0, 0);
sem_init(&printSem, 0, 1);
sem_init(&sthr1, 0, 0);
for (int i = 0; i < 2;i++)
sem_init(&sthr2[i], 0, 0);
for (int i = 0; i < 2;i++)
sem_init(&sthr3[i], 0, 0);
sem_init(&idInitializationSemMainToThread, 0, 0);
sem_init(&idInitializationSemThreadToMain, 0, 0);
int *pnum =(int *) malloc(sizeof(int));
for (int j = 0; j < THR2NUM;j++){
*pnum = j;
pthread_create(&thr2[j], NULL, thread2, (void *)pnum);
sem_post(&idInitializationSemMainToThread);
printString("thr2 "+to_string(j)+ " created");
sem_wait(&idInitializationSemThreadToMain);
}
for (int k = 0; k < THR3NUM;k++){
*pnum = k;
pthread_create(&thr3[k], NULL, thread3,(void *) pnum);
sem_post(&idInitializationSemMainToThread);
printString("thr3 "+to_string(k)+ " created");
sem_wait(&idInitializationSemThreadToMain);
}
for (int i = 0; i < THR1NUM;i++){
*pnum = i;
pthread_create(&thr1[i], NULL, thread1,(void *) pnum);
sem_post(&idInitializationSemMainToThread);
printString("thr1 "+to_string(i)+ " created");
sem_wait(&idInitializationSemThreadToMain);
}
sem_post(&sthr2[0]);
sem_post(&sthr3[0]);
sem_post(&sthr1);
for (int i = 0; i < THR1NUM;i++){
pthread_join(thr1[i], NULL);
printString("thr1 "+to_string(i)+ " joined");
}
for (int i = 0; i < THR2NUM; i++){
pthread_cancel(thr2[i]);
printString("thr2 "+to_string(i)+ " exited");
}
for (int i = 0; i < THR3NUM;i++){
pthread_cancel(thr3[i]);
printString("thr3 "+to_string(i)+ " exited");
sem_post(&printSem);
}
sem_destroy(&s12);
sem_destroy(&s21);
sem_destroy(&s13);
sem_destroy(&s31);
sem_destroy(&sthr1);
free(pnum);
}
// function to print strings atomically.
void printString(string str){
sem_wait(&printSem);
printf("%s\n", str.c_str());
sem_post(&printSem);
}
I'm new to pthread and attempting to implement a producer/consumer problem that will let the user pick buffer size, # of producers, # of consumers, and total # of items. I've been looking through what I thought were similar things on stack overflow, but can't seem to get it right.
My code has a main class and it spawns producers and consumers. It hands the producers and consumers a pointer to a stack initialized in main (or at least I'm trying to). I thought that what I was doing was legal and in CLion I get the predictive text options I want so I thought I linked it properly but I'm segfaulting when I try to read the top element.
I used GDB to make sure I knew what line I was crashing on, but don't understand what's wrong with my setup. While debugging I confirmed that a producer goes through its push() command first, but the consumer fails when attempting top() or pop(). I'd seen some threads here where the OP had problems because they didn't join their threads, but I am so I'm a little lost.
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <stack>
#include <cstring>
#include <semaphore.h>
#include <pthread.h>
#define N 10000
sem_t mutex;
sem_t fullCount;
sem_t emptyCount;
int iCount = 0;
typedef struct _thread_data{
int id;
int itemcount;
std::stack<char>* ptr;
}thread_data;
void *producer(void *arg){
std::cout << "spawned producer\n";
thread_data *data = (thread_data *)arg;
while(true){
char message = 'X';
sem_wait(&emptyCount);
sem_wait(&mutex);
if(iCount < data->itemcount){
data->ptr->push(message);
iCount++;
char temp [25];
sprintf(temp, "p:<%u>, item: %c, at %d\n", data->id, message, data->ptr->size());
std::cout << temp;
//std::cout << "hi I'm a producer\n";
sem_post(&mutex);
sem_post(&fullCount);
}
else{
sem_post(&fullCount);
sem_post(&mutex);
pthread_exit(nullptr);
}
}
}
void *consumer(void *arg){
std::cout << ("spawned consumer\n");
thread_data *data = (thread_data *)arg;
while(true){
char message;
sem_wait(&fullCount);
sem_wait(&mutex);
if(iCount < data->itemcount) {
message = data->ptr->top(); //SEGFAULT
char temp[25];
printf(temp, "c:<%u>, item: %c, at %d\n", data->id, message, data->ptr->size());
data->ptr->pop();
std::cout << temp;
//std::cout << "Hi I'm a consumer\n";
sem_post(&mutex);
sem_post(&emptyCount);
}
else if (iCount == data->itemcount){
message = data->ptr->top(); //SEGFAULT
char temp[25];
printf(temp, "c:<%u>, item: %c, at %d\n", data->id, message, data->ptr->size());
data->ptr->pop();
std::cout << temp;
sem_post(&emptyCount);
sem_post(&mutex);
pthread_exit(nullptr);
}
else{
sem_post(&mutex);
pthread_exit(nullptr);
}
}
}
int main(int argc, char *argv[]){
int bufferSize = N;
int pThreadCount,cThreadCount,itemCount;
for (int x = 0; x < argc; ++x) {
if(strcmp(argv[x],"-b") == 0){
bufferSize = atoi(argv[x+1]);
}
if(strcmp(argv[x],"-p") == 0){
pThreadCount = atoi(argv[x+1]);
}
if(strcmp(argv[x],"-c") == 0){
cThreadCount = atoi(argv[x+1]);
}
if(strcmp(argv[x],"-i") == 0){
itemCount = atoi(argv[x+1]);
}
}
sem_init(&mutex,1,1);
sem_init(&fullCount,1,0);
sem_init(&emptyCount,1,bufferSize);
std::stack<char> myStack;
pthread_t myPThreads[pThreadCount];
thread_data thrData[pThreadCount];
pthread_t myCThreads[cThreadCount];
thread_data cThrData[cThreadCount];
for (int i = 0; i < pThreadCount; ++i) {
thrData[i].id = i;
thrData[i].itemcount = itemCount;
thrData[i].ptr = &myStack;
pthread_create(&myPThreads[i], NULL, producer, &thrData[i]);
}
for (int i = 0; i < cThreadCount; ++i) {
cThrData[i].id = i;
cThrData[i].itemcount = itemCount;
thrData[i].ptr = &myStack;
pthread_create(&myCThreads[i], NULL, consumer, &cThrData[i]);
}
for (int k = 0; k < pThreadCount; ++k) {
pthread_join(myPThreads[k], NULL);
}
for (int j = 0; j < cThreadCount; ++j) {
pthread_join(myCThreads[j], NULL);
}
return 0;
}
iCount <= data->itemcount is always true. consumer never exits the loop. At some point, it exhausts the stack, and the subsequent top() call exhibits undefined behavior.
cThrData[i].ptr is never initialized, for any i. consumer calls top() through an uninitialized pointer, whereupon the program exhibits undefined behavior.
Hi I'm trying to write an algorithm for solving the producer-consumer problem and I've hit a roadblock. This is the output I am getting from my code:
Producing: 6
6 0 0 0 0 0 0 0 0 0 END
and then the program exits. I'm not sure where I went wrong? Did I do something wrong in creating a circular buffer?
#include <iostream>
#include <pthread.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <fstream>
using namespace std;
#define BUFFER_SIZE 10
void *produce(void *);
void *consume(void *);
int produceItem(void);
void insertItem(int item);
void removeItem(void);
void printBuffer(void);
int head = 0;
int tail = 0;
int item;
int bufferCount = 0;
pthread_t producer, consumer;
pthread_cond_t Buffer_Not_Full=PTHREAD_COND_INITIALIZER;
pthread_cond_t Buffer_Not_Empty=PTHREAD_COND_INITIALIZER;
pthread_mutex_t lock;
sem_t sem_filledSlots;
sem_t sem_emptySlots;
int buffer[BUFFER_SIZE];
int main() {
int emptyCount;
int item;
srand (time(NULL));
sem_init(&sem_filledSlots, 0, 0);
sem_init(&sem_emptySlots, 0, BUFFER_SIZE);
sem_getvalue(&sem_emptySlots, &emptyCount);
pthread_create (&producer, NULL, &produce, NULL);
pthread_create (&consumer, NULL, &consume, NULL);
return 0;
}
void *produce(void *)
{
for(int i = 0; i <15; i++)
{
item = produceItem();
sem_wait(&sem_emptySlots);
pthread_mutex_lock(&lock);
printf("Producing: %d \n", item);
buffer[head] = item;
head = (head + 1) % BUFFER_SIZE;
printBuffer();
pthread_mutex_unlock(&lock);
sem_post(&sem_filledSlots);
}
}
void *consume(void *)
{
for(int i = 0; i <15; i++)
{
sem_wait(&sem_filledSlots);
pthread_mutex_lock(&lock);
printf("Consuming %d \n", buffer[tail]);
buffer[tail] = 0;
tail = (tail + 1) % BUFFER_SIZE;
bufferCount--;
printBuffer();
pthread_mutex_unlock(&lock);
sem_post(&sem_emptySlots);
}
}
int produceItem(void)
{
int x = (rand()%11 + 1);
return x;
}
void printBuffer(void)
{
for(int i = 0; i <BUFFER_SIZE; i++)
{
printf("%d ", buffer[i]);
}
printf("END \n");
}
you're missing pthread_join before exiting the program:
....
pthread_join(producer,NULL);
pthread_join(consumer,NULL);
return 0;
....