今儿个看了看consumer-producer问题感觉应该比较简单,就打算用C&C++实现一下,好吧果然很简单。
唯一困扰我比较久的问题就是,C和C++的隐藏机制有一部分不是很一样,导致两者代码不能很好的融合。
问题如下:
线程创建时由于C会隐式的把通用指针转换成其他类型指针,但是在C11标准中C++并不会这么做,SO我在这上面浪费了好久的时间FUCK!!!体现出来就是C++的线程函数必须是(void [*])(*) (void *)形式。
下面就直接上代码啦
C代码:
/*
* > @CopyRight
* > PROJECTNAME : PthreadTest
* > FILENAME : Thread.c
* > AUTHOR : Catalpeak
* > TIME : 2018.9.29
* > CONNECTION : 784734297@163.com
* > LIAONING UNIVERSITY LNU
*/
#include "Thread.h"
void
Consumer (void * _msg);
void
Producer (void * _msg);
int main ()
{
char *msg1 = "Consumer pthread has been created";
char *msg2 = "Producer pthread has been created";
char *msg3 = "Consumer pthread created fail";
char *msg4 = "Producer pthread created fail";
char *msg5 = "Consumer pthread join fail";
char *msg6 = "Producer pthread join fail";
pthread_t ConsumerPthread, ProducerPthread;
void * retval; // Return Value
int ConsumerPthreadCreateSuccess = 0, ProducerPthreadCreateSuccess = 0;
int ConsumerPthreadJoinSuccess = 0, ProducerPthreadJoinSuccess = 0;
InitThread ();
ConsumerPthreadCreateSuccess =
pthread_create (&ConsumerPthread, NULL, (void *) &Consumer, (void *) msg1);
if (ConsumerPthreadCreateSuccess != 0) {
printf ("%s\n", msg3);
return 0x00000002;
}
ProducerPthreadCreateSuccess =
pthread_create (&ProducerPthread, NULL, (void *) &Producer, (void *) msg2);
if (ProducerPthreadCreateSuccess != 0) {
printf ("%s\n", msg4);
return 0x00000003;
}
// Start Pthread
ConsumerPthreadJoinSuccess =
pthread_join (ConsumerPthread, &retval);
if (ConsumerPthreadJoinSuccess != 0) {
printf ("%s\n", msg5);
return 0x00000004;
}
ProducerPthreadJoinSuccess =
pthread_join (ProducerPthread, &retval);
if (ProducerPthreadJoinSuccess != 0) {
printf ("%s\n", msg6);
return 0x00000005;
}
return 1;
}
void
Consumer (void * _msg) {
int nowNumber = 0;
printf ("%s\n", (char *)_msg);
do {
wait (BUFFER_FULL);
wait (PTHREAD_MUTEX);
nowNumber = DeQueue (&buffer);
signature (PTHREAD_MUTEX);
signature (BUFFER_EMPTY);
Caculate (nowNumber);
} while (1);
}
void
Producer (void * _msg) {
int AddNumber = 0;
printf ("%s\n", (char *)_msg);
do {
AddNumber = rand () % 10 + 1;
wait (BUFFER_EMPTY);
wait (PTHREAD_MUTEX);
EnQueue (&buffer, AddNumber);
signature (PTHREAD_MUTEX);
signature (BUFFER_FULL);
} while (1);
}
/*
* > Thread.h
*/
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "../MySignal/mSignal.h"
#include <semaphore.h>
#include <time.h>
#define semaphore pthread_mutex_t
#define BUFFER_EMPTY 1
#define BUFFER_FULL 2
#define PTHREAD_MUTEX 3
Signal buffer;
// @brief mutex LOCK variable
semaphore mutex = PTHREAD_MUTEX_INITIALIZER;
// @brief empty message variable
sem_t empty;
// @brief full message variable
sem_t full;
double SUMNUMBER = 0.0;
void
wait (int type);
void
signature (int type);
void
Caculate (int number);
void InitThread ();
void InitThread () {
sem_init (&empty, 0, 999);
sem_init (&full, 0, 1);
srand ((unsigned int) time (NULL));
InitSignalQueue (&buffer);
}
void
wait (int type) {
switch (type) {
case BUFFER_EMPTY: {
sem_wait (&empty);
} break;
case BUFFER_FULL: {
sem_wait (&full);
} break;
case PTHREAD_MUTEX: {
if (0 != pthread_mutex_lock (&mutex)) {
printf ("ERROR 0x00000008 in Wait \"PTHREAD_MUTEX_LOCK\"\n");
perror ("ERROR 0x00000008 in Wait \"PTHREAD_MUTEX_LOCK\"\n");
exit (EXIT_FAILURE);
}
} break;
default : {
printf ("ERROR 0x00000006 Wait inputs wrong value\n");
} break;
};
return;
}
void
signature (int type) {
switch (type) {
case BUFFER_EMPTY: {
sem_post (&empty);
} break;
case BUFFER_FULL: {
sem_post (&full);
} break;
case PTHREAD_MUTEX: {
if (0 != pthread_mutex_unlock (&mutex)) {
printf ("ERROR 0x00000009 in signature \"PTHREAD_MUTEX_UNLOCK\"\n");
perror ("ERROR 0x00000009 in signature \"PTHREAD_MUTEX_UNLOCK\"\n");
exit (EXIT_FAILURE);
}
} break;
default : {
printf ("ERROR 0x00000007 Signature inputs wrong value\n");
} break;
};
return;
}
void
Caculate (int number) {
SUMNUMBER += number;
if (SUMNUMBER >= 10000000000.0) {
SUMNUMBER = 0.0;
}
printf ("%.lf\n", SUMNUMBER);
}
/*
* > mSignal.h
*/
/* @CopyRight 2018-9-21 21:52 LiaoNing University
* Author : Catalpeak
* Data : 2018-9-21
* connection : 784734297@163.com
*/
#ifndef MSIGNAL_H
#define MSIGNAL_H
#include <stdio.h>
// Change Type of Element here
#define ElemType char
#define SIGNALLENGTH 1000 // The length of all signals in one period
typedef struct Signal {
ElemType signal [SIGNALLENGTH]; // Save Element
int SignalSize; // The MAX Size of Signal Queue
int head; // The number point to head of Queue
int tail; // The number point to tail of Queue
} Signal ;
/* Function : Initialize Signal Queue
* Para : struct Signal pointer
* Return : void
*/
void InitSignalQueue (Signal* _signal);
/* Function : Insert a value in signal's tail
* Para : ElemType macro definition
* Para : struct Signal pointer
* Return : void
*/
void EnQueue (Signal* _signal, ElemType value);
/* Function : Get the first element of signal vector
* Para : struct Signal signal pointer
* Return : ElemType
*/
ElemType DeQueue (Signal* _signal);
/* Function : judge if this Queue is empty
* Para : struct signal pointer
* Return : int , 1 - yes \ 2 - no
*/
int IfEmpty (Signal* _signal);
/* Function : judge if this Queue is filled
* Para : struct signal pointer
* Return : int , 1 - yes / 2 - no
*/
int IfFull (Signal* _signal);
#endif // MSIGNAL_H
/*
* > mSignal.c
*/
/* @CopyRight 2018-9-21 21:52 LiaoNing University
* Author : Catalpeak
* Data : 2018-9-21
* connection : 784734297@163.com
*/
#include "mSignal.h"
void InitSignalQueue (Signal* _signal) {
_signal->head = 0;
_signal->tail = 0;
_signal->SignalSize = SIGNALLENGTH;
}
void EnQueue(Signal* _signal, ElemType value) {
if ((_signal->tail + 1) % _signal->SignalSize == _signal->head) {
// Signal Queue has filled can't insert
} else {
_signal->signal [_signal->tail] = value;
_signal->tail = (_signal->tail + 1) % _signal->SignalSize;
}
}
ElemType DeQueue (Signal* _signal) {
int temp;
if (_signal->head == _signal->tail) {
// This Queue is empty can't get element
} else {
temp = _signal->signal [_signal->head];
_signal->head = (_signal->head + 1) % _signal->SignalSize;
}
return temp;
}
int IfEmpty (Signal* _signal) {
if (_signal->head == _signal->tail) {
return 1;
} else {
return 0;
}
}
int IfFull (Signal* _signal) {
if ((_signal->tail + 1) % _signal->SignalSize == _signal->head) {
return 1;
} else {
return 0;
}
}
C++代码如下:
/*
* > main.cpp
*/
#include "../Header/main.h"
int main ()
{
pthread_t consumerPthread, producerPthread;
char *_msg1 = "FUCK1";// = "Consumer thread has been created";
char *_msg2 = "FUCK2";// = "Producer thread has been created";
int returnProducer, returnConsumer;
void *retConsumer, *retProducer;
returnConsumer = pthread_create (&consumerPthread, NULL, Consumer, (void *) _msg1);
returnProducer = pthread_create (&producerPthread, NULL, Producer, (void *) _msg2);
returnConsumer = pthread_join (consumerPthread, &retConsumer);
returnProducer = pthread_join (producerPthread, &retProducer);
return 1;
}
void* Producer (void * msg) {
printf ("%s\n", (char *)msg);
do {
//Sleep (100);
while (produceMutex < 0);
produceMutex--;
while (mutex <= 0);
mutex--;
/*
cout << "In Producer thread" << endl;
cout << "produceMutex is : " << produceMutex << endl;
cout << "consumeMutex is : " << consumeMutex << endl;
cout << "mutex should be 0 " << "And now is ; " << mutex << endl;
*/
int temp = rand () % 10;
buffer [consumeMutex] = to_String (temp, 1);
//cout << buffer [consumeMutex] << endl;
mutex++;
consumeMutex++;
} while (1);
return (void*) 1;
}
void* Consumer (void * msg) {
printf ("%s\n", (char*)msg);
do {
//Sleep (100);
while (consumeMutex <= 0);
consumeMutex--;
while (mutex <= 0);
mutex--;
/*
cout << "In Consumer thread" << endl;
cout << "produceMutex is : " << produceMutex << endl;
cout << "consumeMutex is : " << consumeMutex << endl;
cout << "mutex should be 0 " << "And now is ; " << mutex << endl;
*/
cout << buffer [consumeMutex] << endl;
mutex++;
produceMutex++;
} while (1);
return (void*) 1;
}
/*
* > main.h
*/
#include <iostream>
#include <string>
#include <pthread.h>
#include <time.h>
#include <windows.h>
#include <cstdio>
#include "../../utils/utils.h"
using namespace std;
// The size of buffer
#define SIZE_ 10
// Mutually variable
int mutex = 1;
// consumer Mutex
int consumeMutex = 0;
// Produce Mytex
int produceMutex = SIZE_;
// Buffer for save
string buffer [SIZE_];
void*
Producer (void * msg);
void*
Consumer (void * msg);
/*
* > utils.h
*/
#include <string>
#define API_ ;
API_ std::string to_String(int n, int max);
/*
* > utils.cpp
*/
#include "utils.h"
std::string to_String(int n, int max)
{
int m = n;
char s[max];
char ss[max];
int i=0,j=0;
if (n < 0)// ´¦Àí¸ºÊý
{
m = 0 - m;
j = 1;
ss[0] = '-';
}
while (m>0)
{
s[i++] = m % 10 + '0';
m /= 10;
}
s[i] = '\0';
i = i - 1;
while (i >= 0)
{
ss[j++] = s[i--];
}
ss[j] = '\0';
return ss;
}
我的编辑器不支持.cc的后缀,写cpp感觉好不舒服啊啊啊啊。