索引到信号量数组中
Indexing into an array of semaphores
假设我初始化了两个全局信号量数组
semaphore empty[someNum];
和
semaphore full[someNum];
并且CCD_ 3被初始化为
const int someNum = 3;
(全球)
我将有一个名为init()
的方法,里面有一个for-loop
来帮助索引这些数组。
for (index=0; index<someNum; index++) num[index]=0;
我的目标是使用像wait
和signal
这样的命令——数组中的某些信号量,例如,如果num
已满,那么我不希望我的生产者在其中放置值。
在init()
内部,我知道我需要初始化循环体中的所有信号量。到目前为止,我已经尝试过
empty[index] = create_semaphore(1)
full[index] = create_semaphore(0)
在我想要预处理动作wait
和signal
的方法内部,例如
wait(empty) ;
但我又犯了错误。我知道这是因为我使用的是数组的名称,而不是特定的信号量。
所以我的问题是,如何正确地索引到for-loop
中的数组中以指定一个信号量?
感谢您的任何和所有投入!如果你有任何问题,请随时要求澄清!请耐心等待,信号量对我来说是一个新概念
注意
命令CCD_ 18存在于与该命令相关联的另一程序中。
编辑
foodPass.cpp
#include <iostream>
#include <sched.h>
#include <time.h>
#include <pthread.h>
#include <string>
#include "sem.h"
using namespace std ;
/* ######################################## */
/* Misc Data Types */
/* ######################################## */
/* A data type - a struct with an int field
to represent a child ID at the program level. */
struct threadIdType
{
int id ;
};
/* ######################################## */
/* Global Variables */
/* ######################################## */
//const int numTrivets = 6 ;
const int numTrivets = 3 ;
const int numDiners = numTrivets - 1 ;
const int maxDishNames = 13 ;
//const int numDishNames = 13 ;
const int numDishNames = 5 ;
int trivet[numTrivets] ;
string dishName[maxDishNames];
/* Here declare the semaphores and other variables you will
need to synchronize threads. */
sim_semaphore empty[numTrivets] ;
sim_semaphore full[numTrivets] ;
/* child_t are global variables to represent the
dynamically-created threads. */
pthread_t child_t[numTrivets] ;
/* ######################################## */
/* "Special" Global Variables */
/* ######################################## */
/* Code in sem.cpp "expects" the two variables below to be here.
This particular program does not use "checking." */
/* "Checking" is just a flag that you set to 1 if you want lots of
debugging messages and set to 0 otherwise. The semaphore code in
sem.cpp imports "checking". Therefore the semaphore operations
will write lots of messages if you set checking=1. */
int checking ;
/* In some programs, we use the "stdoutLock" variable declared below to
get intelligible printouts from multiple concurrent threads that write
to the standard output. (There has to be something to prevent the
output of the threads from interleaving unintelligibly on the standard
output, and we can't use semaphores if the semaphore code is writing
messages too.)
To print a message to standard output, a thread first locks standard
output, then writes, then unlocks standard output. See files sem.cpp
or conc.cpp for examples of code that write messages in this manner.
WARNING: DON'T change how the locking of standard output is done
until you've thought a WHOLE lot about the consequences. In
particular, using semaphores to do the job of stdoutLock can cause
"infinite recursion" under certain circumstances. The reason is that
the semaphore code itself imports "stdoutLock" and writes messages
when the "checking" variable is set to 1. */
pthread_mutex_t stdoutLock ;
/* ################################################## */
/* init */
/* ################################################## */
void init()
{
int index ;
srandom(time((time_t *) 0)); /* INITIALIZE RANDOM NUMBER GENERATOR */
checking = 0 ;
/* Initialize the "special lock" that is used only to get
exclusive access to the screen. */
if ( 0!=pthread_mutex_init(&stdoutLock, NULL) )
{ cout << "MUTEX INITIALIZATION FAILURE!" << endl;
exit(-1) ;}
/* Initialize the trivets to indicate that each contains "no
dish." */
for (index=0; index<numTrivets; index++) trivet[index]=0;
/* Here initialize the semaphores and other variables you use
for synchronization. */
for (index=0; index<numTrivets; index++) full[index] = create_sim_sem(0) ;
for (index=0; index<numTrivets; index++) empty[index] = create_sim_sem(1) ;
/* Give some mnemonic names to the dishes. The first name is
used for an empty trivet. The last name denotes the check
(bill) for the meal. This is coded so no changes are needed
here as long as the value of "numDishNames" is between 2 and
13. */
dishName[0]="no dish";
dishName[1]="vegetable soup" ;
dishName[2]="bread and butter" ;
dishName[3]="beets and chickpeas" ;
dishName[4]="hardboiled eggs" ;
dishName[5]="calf tongue" ;
dishName[6]="baked potato" ;
dishName[7]="string beans" ;
dishName[8]="rack of lamb" ;
dishName[9]="salad" ;
dishName[10]="coffee" ;
dishName[11]="flan" ;
dishName[numDishNames-1]="check" ;
}
/* ################################################## */
/* DelayAsMuchAs */
/* ################################################## */
void delayAsMuchAs (int limit)
{
int time, step;
time=(int)random()%limit;
for (step=0;step<time;step++) sched_yield() ;
}
/* ################################################## */
/* Server */
/* ################################################## */
/*
The mother thread spawns a child thread that executes this
function. This function carries out the job of the server
at the restaurant.
*/
void * Server(void * ignore)
{
int i, j, delayLimit=100 ;
for (i=1; i<numDishNames; i++)
{
/* I delay a random time before I "feel like" placing
another dish on the table.*/
delayAsMuchAs(delayLimit);
/* When the trivet is available, I place the dish on the
trivet to my right. */
/* Here do a synchronization task. One thing you need to
do is be sure that you are not going to place a dish on
a trivet that alreay has a dish on it. *DO NOT* just
busy-wait until you see that the trivet is empty. */
wait_sem(empty[i]) ;
trivet[0]=i; // put dish #i onto trivet #0
pthread_mutex_lock(&stdoutLock) ;
cout << "Server places " << dishName[trivet[0]]
<< " on trivet #0." << endl ;
pthread_mutex_unlock(&stdoutLock);
/* Here you may want to a synchronization task --
something that "opens the door" for diner #0 to get
access to the new dish. */
signal_sem(full[i]) ;
}
pthread_exit ((void *)0) ;
}
/* ################################################## */
/* Diner */
/* ################################################## */
/*
The mother thread spawns child threads that execute this
function. This function carries out the job of one of the
diners at the restaurant.
*/
void * Diner(void * postnPtr)
{
/* Type cast the parameter to recover "position" -- which
tells me the position at which I am seated at the
table. */
int position = ((threadIdType *)(postnPtr))->id ;
int i, j, delayLimit=100 ;
for (i=1; i<numDishNames; i++)
{
/* I delay a random time before I "feel like" picking up the next
dish.*/
delayAsMuchAs(delayLimit);
/* When available, I pick up the next new dish on my left. */
/* Here do a synchronization task. One thing you need to
do is be sure that there is a new dish on the trivet to
your left now, and that the person on your left has
"let go" of it. */
wait_sem(full[i]);
/* I declare what I am doing */
pthread_mutex_lock(&stdoutLock) ;
cout << "Diner number "<< position ;
if (i<numDishNames-1) cout << " enjoys ";
else if (position<numDiners-1) cout << " examines " ;
else cout << " examines and pays " ;
cout << dishName[trivet[position]] << endl ;
pthread_mutex_unlock(&stdoutLock);
/* I delay a random time to simulate the time it takes for me to
serve myself some of what is on the dish -- or look at the
check. */
delayAsMuchAs(delayLimit);
/* When available, I place the dish on the trivet to my right. */
/* Here do a synchronization task. One thing you need to
do is be sure that the trivet on your right does not
have a dish on it now.*/
wait_sem (empty[i]);
pthread_mutex_lock(&stdoutLock) ;
cout << "Diner number "<< position << " moves "
<< dishName[trivet[position]] << " from trivet #"
<< position << " to trivet #" << position+1 << endl;
pthread_mutex_unlock(&stdoutLock);
/* transfer the dish on my left to trivet on my right */
trivet[position+1]=trivet[position] ;
/* mark trivet on my left as empty */
trivet[position]=0;
/* Here do a synchronization task. You have transferred a
dish from your left to your right. The person on your
left will need to find out that the trivet on your left
is now empty. The person on your right will need to
find out that the trivet on your right now has a new
dish on it. */
signal_sem(empty[i]);
signal_sem(full[i]);
}
delete((threadIdType *)(postnPtr)) ;
pthread_exit ((void *) 0) ;
}
/* ################################################## */
/* Busser */
/* ################################################## */
/*
The mother thread spawns children and then executes this
function. This is convenient because this function should
be the last to exit. This function carries out the job of
the busser at the restaurant.
*/
void * Busser (void * ignore)
{
int i, j, delayLimit=100 ;
for (i=1; i<numDishNames; i++)
{
/* I delay a random time before I "feel like" bussing another
dish.*/
delayAsMuchAs(delayLimit);
/* When another dish is on the trivet to my right I remove it. */
/* Here do a synchronization task. One thing you need to
do is be sure that there is a new dish on the trivet to
your left now, and that the person on your left has
"let go" of it. */
wait_sem (full[i]) ;
pthread_mutex_lock(&stdoutLock) ;
cout << "Busser removes "
<< dishName[trivet[numTrivets-1]] << " from trivet #"
<< numTrivets-1<< "." << endl ;
pthread_mutex_unlock(&stdoutLock);
trivet[numTrivets-1]=0; // remove the dish.
/* Here do a synchronization task. The person on your left
will need to find out that the trivet on your left is
now empty. */
signal_sem (empty[i]);
}
return ignore ;
}
/* ################################################## */
/* Main */
/* ################################################## */
int main()
{
init();
cout << endl << endl;
cout << "Welcome to the restaurant!" << endl ;
cout << numDiners << " will be dining." << endl ;
cout << "The meal will consist of " << numDishNames-2
<< " dishes." << endl;
cout << "Bon appetite!" << endl ;
cout << endl << endl;
int i;
/* This is a pointer to a struct that contains an int
field - it is a convenient data type to use as the
parameter to the child function. */
threadIdType * idPtr ;
for (i=0; i<numDiners; i++)
{
/* This records the current index as this child's ID */
idPtr = new threadIdType ;
idPtr->id = i ;
if (0!=pthread_create(&child_t[i], NULL, Diner, (void *) idPtr))
{cout << "THREAD CREATION FAILURE!" << endl; exit(-1) ;}
if (0!=pthread_detach(child_t[i]))
{cout << "THREAD DETACHMENT FAILURE!" << endl ; exit(-1) ;}
}
if (0!=pthread_create(&child_t[numDiners], NULL, Server, (void *) 0))
{cout << "THREAD CREATION FAILURE!" << endl; exit(-1) ;}
if (0!=pthread_detach(child_t[numDiners]))
{cout << "THREAD DETACHMENT FAILURE!" << endl ; exit(-1) ;}
Busser((void *) 0) ;
cout << endl << endl;
cout << "Thank you for coming!" << endl ;
cout << endl << endl;
return 0 ;
}
好的,我发现了我的问题。
虽然我在init()
中正确初始化了索引数组,但
for (index=0; index<numTrivets; index++) full[index] = create_sim_sem(0) ;
for (index=0; index<numTrivets; index++) empty[index] = create_sim_sem(1) ;
我的问题实际上来自wait
和signal
命令。
在server()
中,它是一个纯生产者,只负责第一个数组索引0
,因此命令只是
CCD_ 24和CCD_ 25
在diner()
中,它稍微复杂一些。它充当生产者和消费者之间的混合体,这意味着我们不能只使用0
和1
,所以我们看看trivet[]
是如何索引单个信号量并借用它的,然后我们得到
someNum
0
此外,diner()
还需要担心两个位置。因此,我们必须使下一个位置具有排他性,因此我们初始化trivet[position+1]
,并在处理右侧的waits
和signals
时再次借用它。
最后,我们有一个纯粹作为消费者的busser()
。只有当他的位置满了,我们才能给他发信号。由于三角架的数量是可互换的,(numTrivets
)我们不能简单地放入1
,因为下次可能有2个以上的点。因此,我们只需要输入像这样的命令
CCD_ 38然后CCD_ 39
然后我得到了我想要的输出。
感谢所有给我意见的人,我希望我的回答对所有像我一样困惑的人都有用。
- 张量(多维数组)是树前瞻数据的有效存储类型吗?
- 为什么我不能将 op 结果乘以常量特征张量数组
- 在 tensorflow c++ api 中,如何从张量中保存图片或数组
- 如何将张量转换为图像数组
- C++ 数组将所有值调整相同的量
- 将shared_ptr分配给数组的偏移量
- 函数采用预期大小的数组,向用户发出信号
- C++ 函数返回带有偏移量的数组
- 将数组的内容从偏移量写入c++向量
- 严格的混叠警告,创建对无符号字符数组 + 偏移量的uint32_t引用
- 我有一个对象数组,我想发出一个包含这些对象中的一个的信号。但信号不能是指针
- 索引到信号量数组中
- 信号量数组初始化为NULL,seg错误
- 多维数组(或张量)和向量的乘积
- 将一个char数组传递给函数模板,这样gcc就可以判断出它是一个字面量
- OS X中的信号量数组
- 如何有效地等待一组信号量
- c++ pthreads返回数组偏移量
- 将数组连接到Qt中的信号槽机制
- 指向成员(偏移量)的指针数组作为C++中的模板参数