firstworks Programming with Rudiments using the semaphoreset class

Using the semaphoreset class

Semaphores allow seperate processes or threads to synchronize activities. The semaphoreset class provides methods for creating and accessing semaphores.

This program creates a set of semaphores and prints out 1 and 3, using the semaphores to synchronize with a second program.

> #include <rudiments/file.h>
> #include <rudiments/permissions.h>
> #include <rudiments/semaphoreset.h>
> #include <rudiments/error.h>
> #include <rudiments/stdio.h>
> int main(int argc, const char **argv) {
> // create a file named "sem"
> file::createFile("sem",permissions::evalPermString("rw-------"));
> // generate a unique semaphore id based on the file
> key_t semid=file::generateKey("sem",1);
> // Create a semaphore set, containing 2 semaphores.
> // Initialize them to 0 and 1 respectively.
> int32_t vals[2]={0,1};
> semaphoreset sem;
> if (sem.create(semid,permissions::evalPermString("rw-------"),2,vals)) {
> // loop 10 times, printing 2 and 4, using the
> // semaphores to synchronize with another process
> for (int i=0; i<10; i++) {
> sem.wait(0);
> stdoutput.printf("2\n");
> sem.signal(1);
> sem.wait(0);
> stdoutput.printf("4\n");
> sem.signal(1);
> }
> } else {
> // an error must have occurred
> char *err=error::getErrorString();
> stdoutput.printf("error: %s\n",err);
> delete[] err;
> }
> // remove the file "sem"
> file::remove("sem");
> }

This program attaches to the semaphore set created by the first program and prints out 2 and 4, using the semaphores to synchronize with a first program.

> #include <rudiments/file.h>
> #include <rudiments/permissions.h>
> #include <rudiments/semaphoreset.h>
> #include <rudiments/error.h>
> #include <rudiments/stdio.h>
> int main(int argc, const char **argv) {
> // generate a semaphore id based on the file "sem"
> // (which was created by the other process)
> key_t semid=file::generateKey("sem",1);
> // attach to the semaphore set keyed to sem containing 2 semaphores
> semaphoreset sem;
> if (sem.attach(semid,2)) {
> // loop 10 times, printing 1 and 3, using the
> // semaphores to synchronize with another process
> for (int i=0; i<10; i++) {
> sem.wait(1);
> stdoutput.printf("1\n");
> sem.signal(0);
> sem.wait(1);
> stdoutput.printf("3\n");
> sem.signal(0);
> }
> } else {
> // an error must have occurred
> char *err=error::getErrorString();
> stdoutput.printf("error: %s\n",err);
> delete[] err;
> }
> }

These programs must both be run to the background.

No matter what order the programs are started in, they will always print out:

1
2
3
4
1
2
3
4
etc.

Note that on unix-like systems, the first program should not be killed. Semaphore sets are persistent in the kernel and remain unless specifically removed. The semaphoreset class will remove the semaphore set that it created when the instance of the class is destroyed, but if the first process is killed then the semaphore set will persist and subsequent attempts to run the program will fail with a cryptic error like "File exists" or similar.

If this happens, most unix-like systems provide utilites for examining and cleaning up semaphore sets.

Running ipcs -s allows you to examine semaphore sets. It ought to return something like:

>     ------ Semaphore Arrays --------
>     key        semid      owner      perms      nsems
>     0x010114f4 188678177  dmuse      600        2

The shmid can then be used with the ipcrm utility to remove the shared memory segment. For example: ipcrm -s 188678177

None of this is an issue on Windows systems.