ONPOSIX  2.0
 All Classes Namespaces Files Functions Variables Enumerator Friends Macros Pages
OnPosix Library


Minimal Posix C++ library

Author
Evidence Srl - www.evidence.eu.com



Introduction

OnPosix is a tiny library to abstract POSIX mechanisms to C++ developers. It offers threading, networking, logging, IPC, etc.

Most features offered by this library can be found either inside the Boost library or in a standard library compliant with the C++11 standard.
Unfortunately, however, for some embedded Linux devices, these libraries cannot represent viable solutions, due to the lack of memory space (for the Boost libraries) and the lack of a new C++ compiler (e.g., on Xilinx MicroBlaze). On these platforms, the OnPosix library represents a good and cheap solution to have object-oriented POSIX mechanisms.

The library is available both as a shared (.so) and a static (.a) library.




License

The library has been developed in the context of the ERA project, financially supported by the European commission under the FP7 program.

The library is licensed under version 2 of the GNU LIBRARY GENERAL PUBLIC LICENSE (LGPL).
See file LICENSE for more details.




Download

Type

git clone git://git.code.sf.net/p/onposix/code onposix-code

or download a zip archive from Sourceforge.



Installation

To build the library, just type:

make

The library is built both as shared library (.so) and static library (.a).

To install the library on your system, type

make install

To install the library in a specific directory, type

make TARGET_DIR=/absolute/path install

Documentation is created through Doxygen. To generate the documentation, type

make doc

Unit testing is done through the Google C++ Testing Framework. To test the library, specify the googletest path by setting the GTEST_INCLUDE_DIR and GTEST_LIB_DIR variables in the Makefile and type

make test
./test



Examples of usage

Some examples about the characteristics offered by the library:

Processes

The library provides the class onposix::Process to run a function or a program through fork() and fork()+execvp(), respectively.

Example of usage to run a function:

void function ()
{
//...
}
int main ()
{
Process p(function);
}

Example of usage to run a program — i.e., through for()+execvp()

int main ()
{
std::vector<std::string> args;
args.push_back("-l");
args.push_back("*.cpp");
Process p("ls", args);
}

Threads

The library offers basic mechanisms to create, start and stop threads.
On Linux, it allows also to set scheduling parameters, thread affinity and signal handling.

The simplest case to create a thread is to use the onposix::SimpleThread class:

void myfunction (void* arg);
int main ()
{
int b;
SimpleThread t (myfunction, (void*) b);
t.start();
t.waitForTermination();
}

For more complex cases, or if you need a better exchange of arguments (e.g., return values), create your own class by inheriting from onposix::AbstractThread and specifying a run() method. Here we provide a small example. Information about all available methods can be found in the onposix::AbstractThread class.

class MyThread: public AbstractThread {
// Put thread arguments here
public:
MyThread() {
// Initialize arguments here
}
void run() {
// Put thread code here
// Access arguments as normal attributes
}
};
int main ()
{
MyThread t;
t.blockSignal(SIGTERM);
t.start();
t.waitForTermination();
}

Mutual exclusion

PosixMutex m;
m.lock();
//....
m.unlock();

Condition variables

PosixCondition c;
PosixMutex m;
c.wait(&m);
//....
c.signal();

File descriptors

FileDescriptor fd ("/tmp/myfile", O_RDONLY);
Buffer b (10);
fd.read (&b, b.getSize());
fd.close();

It is also possible to use asynchronous read/write operations:

void read_handler(Buffer* b, size_t size)
{
//...
}
FileDescriptor fd ("/tmp/myfile", O_RDONLY);
Buffer b (10);
fd.async_read (read_handler, &b, b.getSize());
fd.close();

Socket descriptors

The library offers mechanisms for both connection-oriented (e.g., TCP) and connection-less (e.g., UDP) communications. Communications can be either AF_UNIX or AF_INET. Here is a small example about a TCP client-server application. More information can be found in the description of classes onposix::StreamSocketServer, onposix::StreamSocketServerDescriptor, onposix::StreamSocketClientDescriptor, onposix::DgramSocketClientDescriptor and onposix::DgramSocketServerDescriptor.

Server-side:

void read_handler(Buffer* b, size_t size)
{
//...
}
int port = 1234;
StreamSocketServer serv (port);
while (true) {
StreamSocketServerDescriptor des (serv);
Buffer b (10);
// Synchronous read:
des.read(&b, b.getSize());
//...or asynchronous read:
fd.async_read (read_handler, &b, b.getSize());
// ...
}

Client-side:

int port = 1234;
std::string address = "192.168.10.133";
StreamSocketClientDescriptor des(address, port);
Buffer b (10);
des.write(&b, b.getSize());

Pipes

Pipe p;
Buffer b (10);
p.read(&b, b.getSize());
p.close();

FIFOs (AKA "named pipes")

FifoDescriptor fd ("/tmp/myfifo", O_RDONLY);
Buffer b (10);
fd.read (&b, b.getSize());

Logging

Log messages can be printed to console and/or to a file with different log levels.

The following log levels can be set for both LOG_LEVEL_CONSOLE and LOG_LEVEL_FILE:

  • LOG_NOLOG: No logging
  • LOG_ERRORS: Only log errors
  • LOG_WARNINGS: Log warnings and errors
  • LOG_ALL: Log all messages (debug messages included)

These values can be set directly inside the file include/Logger.hpp, or when including this file as follows:

#define LOG_LEVEL_CONSOLE LOG_WARNINGS
#define LOG_LEVEL_FILE LOG_ALL
#include "Logger.hpp"

To log a message, use

LOG_FILE("/tmp/myproject");
DEBUG("hello " << "world");
DEBUG("something " << "strange");
DEBUG("this is an error");

Timing

Time t1;
std::cout << t1.getSeconds() << " " << t1.getNSeconds() << std::endl;

Watching multiple descriptors

class FileReader: public AbstractDescriptorReader {
FileDescriptor fd1_;
FileDescriptor fd2_;
public:
FileReader(){
//...
monitorDescriptor(fd1_);
monitorDescriptor(fd2_);
}
void dataAvailable(PosixDescriptor& des) {
std::cout << des.getDescriptorNumber() << "ready" << std::endl;
}
};

Assertions

Assertions provided by this library work also when code is compiled with the -NDEBUG macro.

Example of usage:

int i;

Much more...

The library also offer Observer designer pattern on descriptors (i.e., onposix::DescriptorsMonitor), buffers (i.e., onposix::Buffer) and shared queues (i.e., onposix::PosixSharedQueue and onposix::PosixPrioritySharedQueue).



Support

A mailing list is available on Sourceforge. Fell free to propose feedback, new features and possible improvements.