2015-11-02 31 views
1

的陣列可以說,我初始化信號量的兩個全局陣列,索引到信號量

semaphore empty[someNum];

semaphore full[someNum];

someNum被初始化爲

const int someNum = 3;(全局)

我將有一個名爲init()的方法,裏面是一個for-loop來幫助索引這些數組。

for (index=0; index<someNum; index++) num[index]=0;

我的目標是在陣列中使用的命令一樣waitsignal一定的信號量,例如,如果num是滿的,那麼我不希望我的製片人將值放入它。

裏面的init()我知道我需要初始化循環體中的所有信號量。到目前爲止,我已經嘗試

empty[index] = create_semaphore(1)

full[index] = create_semaphore(0)

和裏面的我想瓶坯waitsignal我試過例如

wait(empty) ;

行動的方法,但我回來錯誤。我知道這是因爲我使用數組的名稱而不是特定的信號量。

所以我的問題是,我如何正確索引到我的for-loop我的陣列指定一個信號量?

感謝您的任何和所有輸入!如果您有任何問題,請隨時要求澄清!請耐心等待,信號量對我來說是一個新概念。

注意

create_semaphore存在於這一個隸屬於另一個程序的命令。

編輯

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 ; 
} 
+0

你在用什麼庫?如果你想等待一個特定的信號量,那麼你將不得不給它的索引。我不確定那就是你想要的。 POSIX信號量基於一個計數器,所以如果我正確理解你的話,可以通過一個單一的信號量來初始化爲正確的值。 – ChiefTwoPencils

+0

好的,我將我的庫添加到了我的編輯 – Junikin

+0

好吧,我想你知道直接問題的答案,即你無法將數組作爲sem傳遞。如果你確定自己有正確的實現,那麼就像遍歷它們並單獨等待它們一樣簡單。但那些阻止電話,所以我不願意提出更多的建議,而沒有看到你在做什麼。 – ChiefTwoPencils

回答

1

好吧,我發現我的問題。

雖然我正確初始化我的索引數組中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) ; 

我的問題其實來自於waitsignal命令。

server()是一個純粹的生產者和只負責第一陣列索引0這樣的命令是簡單地

wait_sem(empty[0])signal_sem(full[0])

diner()它是一個比較複雜的。它作爲生產者和消費者之間的混合,這意味着我們不能只用01,讓我們來看一下如何trivet[]索引單個信號,並借這一點,那麼我們得到

wait_sem(full[position])

此外,有兩個diner()必須擔心的位置。所以,我們必須獨佔下一個位置,所以我們初始化trivet[position+1],並再次借用,當我們正在處理waitssignals是他們的權利。

最後,我們有busser()純粹作爲消費者行事。當他的位置滿了時,我們只會發出信號給他消耗。由於三人間的數量可以互換,(numTrivets)我們不能簡單地放入1,因爲下次可能會有兩個以上的點。因此,我們只需要投入命令,像

wait_sem(full[numTrivets-1])然後signal_sem(empty[numTrivets-1])

,然後我得到我想要的輸出。

謝謝大家給我的意見我希望我的回答對所有那些像我自己一樣困惑的人都有用