PLearn 0.1
Semaphores.cc
Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 // PLearn (A C++ Machine Learning Library)
00004 // Copyright (C) 2000 Yoshua Bengio and University of Montreal
00005 //
00006 
00007 // Redistribution and use in source and binary forms, with or without
00008 // modification, are permitted provided that the following conditions are met:
00009 // 
00010 //  1. Redistributions of source code must retain the above copyright
00011 //     notice, this list of conditions and the following disclaimer.
00012 // 
00013 //  2. Redistributions in binary form must reproduce the above copyright
00014 //     notice, this list of conditions and the following disclaimer in the
00015 //     documentation and/or other materials provided with the distribution.
00016 // 
00017 //  3. The name of the authors may not be used to endorse or promote
00018 //     products derived from this software without specific prior written
00019 //     permission.
00020 // 
00021 // THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
00022 // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00023 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
00024 // NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00026 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031 // 
00032 // This file is part of the PLearn library. For more information on the PLearn
00033 // library, go to the PLearn Web site at www.plearn.org
00034 
00035 
00036 /* *******************************************************      
00037  * $Id: Semaphores.cc 3994 2005-08-25 13:35:03Z chapados $
00038  * This file is part of the PLearn library.
00039  ******************************************************* */
00040 
00041 #include <cstring>
00042 #include <cerrno>
00043 #include <plearn/base/general.h>
00044 #include "Semaphores.h"
00045 
00046 namespace PLearn {
00047 using namespace std;
00048 
00049 ResourceSemaphore::ResourceSemaphore(int nb_semaphores)
00050     : owner(true), n_semaphores(nb_semaphores)
00051 {
00052     // allocate a semaphore 
00053     int rv=semget(IPC_PRIVATE, n_semaphores, 0666 | IPC_CREAT);
00054     if (rv == -1) 
00055         PLERROR("ResourceSemaphore::ResourceSemaphore(%d) semget returns -1, %s",
00056                 nb_semaphores,strerror(errno));
00057     else id.id=rv;
00058     cout << "allocated semaphore " << id.id << endl;
00059     clearAnyLock(); // sets all the semaphore values to 1
00060 }
00061 
00062 ResourceSemaphore::ResourceSemaphore(SemId semid) : id(semid), owner(false)
00063 {
00064     struct semid_ds buf;
00065     semun u;
00066     u.buf = &buf;
00067     int r=semctl(id.id,0,IPC_STAT,u);
00068     if (r == -1)
00069         PLERROR("ResourceSemaphore:: slave ResourceSemaphore(%d) semctl returns -1, %s",
00070                 id.id,strerror(errno));
00071     n_semaphores = u.buf->sem_nsems;
00072 }
00073 
00074 void ResourceSemaphore::lock(int resource)
00075 {
00076     struct sembuf op;
00077     op.sem_num = resource;
00078     op.sem_op = -1;  // wait for value = 1 and then decrement to zero
00079     op.sem_flg = 0;
00080     int rv=semop(id.id,&op,1);
00081     if (rv == -1)
00082         PLERROR("ResourceSemaphore::lock(%d) semop failed, %s",
00083                 resource,strerror(errno));
00084 }
00085 
00086 void ResourceSemaphore::unlock(int resource)
00087 {
00088     if (!locked(resource))
00089         PLERROR("ResourceSemaphore::unlock(%d), trying to unlock an unlocked resource",
00090                 resource);
00091     struct sembuf op;
00092     op.sem_num = resource;
00093     op.sem_op = 1; // increment value back to 1
00094     op.sem_flg = 0;
00095     int rv=semop(id.id,&op,1);
00096     if (rv == -1)
00097         PLERROR("ResourceSemaphore::unlock(%d) semop failed, %s",
00098                 resource,strerror(errno));
00099 }
00100 
00101 bool ResourceSemaphore::locked(int resource)
00102 {
00103     semun v; v.val=0;
00104     int value=semctl(id.id,resource,GETVAL,v);
00105     return (value==0);
00106 }
00107 
00108 void ResourceSemaphore::clearAnyLock()
00109 {
00110     for (int i=0;i<n_semaphores;i++)
00111         clearAnyLock(i);
00112 }
00113 
00114 void ResourceSemaphore::clearAnyLock(int resource)
00115 {
00116     // set the semaphore values to 1 (meaning they are in "unlocked" state")
00117     semun v; v.val=1;
00118     int rv=semctl(id.id,resource,SETVAL,v);
00119     if (rv == -1)
00120         PLERROR("ResourceSemaphore::clearAnyLock(%d) semctl returns -1, %s",
00121                 resource,strerror(errno));
00122 }
00123 
00124 ResourceSemaphore::~ResourceSemaphore()
00125 {
00126     if (owner)
00127     {
00128         semun v; v.val=0;
00129         int rv=semctl(id.id,0,IPC_RMID,v);
00130         if (rv == -1)
00131             PLERROR("ResourceSemaphore::~ResourceSemaphore semctl failed, %s",
00132                     strerror(errno));
00133         cout << "released semaphore " << id.id << endl;
00134     }
00135 }
00136 
00137 CountEventsSemaphore::CountEventsSemaphore(int nb_semaphores)
00138     : owner(true), n_semaphores(nb_semaphores)
00139 {
00140     // allocate a semaphore 
00141     int rv=semget(IPC_PRIVATE, n_semaphores, 0666 | IPC_CREAT);
00142     if (rv == -1) 
00143         PLERROR("CountEventsSemaphore::CountEventsSemaphore(%d) semget returns -1, %s",
00144                 nb_semaphores,strerror(errno));
00145     else id.id=rv;
00146 
00147     cout << "allocated semaphore " << id.id << endl;
00148 
00149     // set the semaphore values to 0 (meaning that initially the counters are at 0)
00150     semun v; v.val=0;
00151     for (int i=0;i<n_semaphores;i++)
00152     {
00153         rv=semctl(id.id,i,SETVAL,v);
00154         if (rv == -1)
00155             PLERROR("CountEventsSemaphore::CountEventsSemaphore(%d) semctl returns -1, %s",
00156                     nb_semaphores,strerror(errno));
00157     }
00158 }
00159 
00160 CountEventsSemaphore::CountEventsSemaphore(SemId semid)
00161     : id(semid), owner(false)
00162 {
00163     struct semid_ds buf;
00164     semun u;
00165     u.buf = &buf;
00166     int r=semctl(id.id,0,IPC_STAT,u);
00167     if (r == -1)
00168         PLERROR("CountEventsSemaphore:: slave CountEventsSemaphore(%d) semctl returns -1, %s",
00169                 id.id,strerror(errno));
00170     n_semaphores = u.buf->sem_nsems;
00171 }
00172 
00173 void CountEventsSemaphore::signal(int type)
00174 {
00175     struct sembuf op;
00176     op.sem_num = type;
00177     op.sem_op = 1; // increment value 
00178     op.sem_flg = 0;
00179     int rv=semop(id.id,&op,1);
00180     if (rv == -1)
00181         PLERROR("CountEventsSemaphore::signal(%d) semop failed, %s",
00182                 type,strerror(errno));
00183 }
00184 
00185 int CountEventsSemaphore::value(int type)
00186 {
00187     semun v; v.val=0;
00188     return semctl(id.id,type,GETVAL,v);
00189 }
00190 
00191 void CountEventsSemaphore::wait(int n_occurences, int type)
00192 {
00193     struct sembuf op;
00194     op.sem_num = type;
00195     op.sem_op = -n_occurences; // wait until n_occurences is reached
00196     op.sem_flg = 0;
00197     int rv=0;
00198     do  // this loop is to deal with possible interrupts which
00199         rv=semop(id.id,&op,1); // will force return of semop before
00200     while (rv==-1 && errno==EINTR);  // the count is reached
00201     if (rv == -1) 
00202         PLERROR("CountEventsSemaphore::wait(%d,%d) semop failed, %s",
00203                 n_occurences,type,strerror(errno));
00204 }
00205 
00206 void CountEventsSemaphore::setValue(int value,int resource)
00207 {
00208     semun v; v.val=value;
00209     int rv=semctl(id.id,resource,SETVAL,v);
00210     if (rv == -1)
00211         PLERROR("ResourceSemaphore::setValue(%d,%d) semctl returns -1, %s",
00212                 value,resource,strerror(errno));
00213 }
00214 
00215 CountEventsSemaphore::~CountEventsSemaphore()
00216 {
00217     if (owner)
00218     {
00219         semun v; v.val=0;
00220         int rv=semctl(id.id,0,IPC_RMID,v);
00221         if (rv == -1)
00222             PLERROR("CountEventsSemaphore::~CountEventsSemaphore semctl failed, %s",
00223                     strerror(errno));
00224         cout << "released semaphore " << id.id << endl;
00225     }
00226 }
00227 
00228 } // end of namespace PLearn
00229 
00230 
00231 /*
00232   Local Variables:
00233   mode:c++
00234   c-basic-offset:4
00235   c-file-style:"stroustrup"
00236   c-file-offsets:((innamespace . 0)(inline-open . 0))
00237   indent-tabs-mode:nil
00238   fill-column:79
00239   End:
00240 */
00241 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=79 :
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines