// Copyright (c) 1999-2000 David Muse
// See the COPYING file for more information.

#ifndef SEMAPHORESET_H
#define SEMAPHORESET_H

#include <pwd.h>
#include <grp.h>
#include <sys/types.h>

// Semaphores allow processes to synchronize their activities.
//
// A semaphore is just a number with two primary operations that can be 
// performed on it: signal() and wait()
// 
// The operations are analagous to:
//
// int  semaphore;
//
// void signal() {
//      semaphore++;            // increment the semaphore
// }
//
// void wait() {
//      while (!semaphore>0);   // wait until the semaphore>0
//      semaphore--;            // decrement the semaphore
// }
//
// The actual signal() and wait() operations are atomic.  There is no chance 
// of another process getting context-switched in and changing the semaphore 
// value between the two lines of code in the wait() process.
//
// Semaphores can be initialized to any number.
// 
// The initial value of the semaphore corresponds to the number of processes
// that will pass directly through their wait() calls without being blocked.
//
// Processes that get blocked calling wait() are placed in a queue.  When 
// another process calls signal(), the process at the head of the queue is 
// unblocked.
//
// A semaphoreset is just a collection of related semaphores.
//
// A semaphoreset is owned by a user and group and has access permissions
// just like a file.

class semaphoreset {
        public:
                        semaphoreset();
                                // Creates a semaphore set.
                virtual ~semaphoreset();
                                // Cleans up and removes the semaphore set
                                // if it was created by create() or 
                                // createOrAttach() below.  If the semaphore
                                // was just attached to, it is not removed.

                int     create(key_t key, mode_t permissions, 
                                        int semcount, int *values);
                                // Creates a semaphore set identified by "key"
                                //      containing "semcount" semaphores.
                                // "key" should be generated using the ftok 
                                //      function. 
                                // "permissions" sets the access permissions
                                //      for the set.
                                // "values" should be an array of starting 
                                //      values for each of the semaphores 
                                //      in the set.
                int     attach(key_t key, int semcount);
                                // Attaches to an already existing semaphore set
                                // identified by "key", containing "semcount" 
                                // semaphores.
                int     createOrAttach(key_t key, mode_t permissions, 
                                                int semcount, int *values);
                                // Attempts to create the semaphore set 
                                // identified by "key".  If this fails, it 
                                // attempts to attach to a semaphore set
                                // identified by "key".

                void    dontRemove();
                        // Instructs the destructor not to remove the semaphore
                        // set if it was created during a call to create() or 
                        // createOrAttach() above.  This is useful if an 
                        // application creates a semaphore set then forks and 
                        // wants to delete the semaphore set in the forked 
                        // process but does not want the semaphore removed from
                        // the system.
                int     forceRemove();
                        // Removes the semaphore set, whether it
                        // was created or attached to.

                void    showErrors();
                        // errors will be printed to stderr
                void    dontShowErrors();
                        // errors will not be printed to stderr

                int     getId();
                        // Returns the internal id for the semaphore set.

                int     wait(int index);
                        // wait on the "index"'th semaphore in the set
                int     signal(int index);
                        // signal on the "index"'th semaphore in the set


                int     waitWithUndo(int index);
                        // wait on the "index"'th semaphore in the set and
                        // undo the wait when the program exits
                int     signalWithUndo(int index);
                        // signal on the "index"'th semaphore in the set and
                        // undo the signal when the program exits


                int     setValue(int index, int value);
                        // set the "index"'th semaphore in the set to "value"
                int     getValue(int index);
                        // return the value of the "index"'th 
                        // semaphore in the set


                int     setUserName(char *username);
                        // makes this semaphore set owned by 
                        // the user "username"
                int     setGroupName(char *groupname);
                        // makes this semaphore set owned by 
                        // the group "groupname"
                int     setUserId(ushort uid);
                        // makes this semaphore set owned by 
                        // the user identified by "uid"
                int     setGroupId(ushort gid);
                        // makes this semaphore set owned by 
                        // the group identified by "gid"
                int     setPermissions(mode_t permissions);
                        // sets the access permissions for this 
                        // semaphore set to "permissions"


                char    *getUserName();
                        // returns the name of the user that owns this
                        // semaphore set
                char    *getGroupName();
                        // returns the name of the group that owns this
                        // semaphore set
                ushort  getUserId();
                        // returns the user id of the user that owns this
                        // semaphore set
                ushort  getGroupId();
                        // returns the group id of the group that owns this
                        // semaphore set
                mode_t  getPermissions();
                        // returns the access permissions for this
                        // semaphore set


                int     getWaitingForZero(int index);
                        // returns the number of processes that
                        // are waiting for the semaphore to become 0
                int     getWaitingForIncrement(int index);
                        // returns the number of processes that
                        // are waiting for the semaphore to increment

        private:
                #include <rudiments/private/semaphoreset.h>

};

#endif