a firstworks project
Rudiments
About Documentation Download Licensing News

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::parsePermString("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::parsePermString("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:

12341234etc.

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.

Copyright 2017 - David Muse - Contact