Enrico Franchi Homepage

Questo sito è obsoleto. La nuova versione di questa pagina è disponibile presso akropolix

This site is old. The new version of this page is available on akropolix

Easy lock

This very simple piece of software shows how we can deal with C resources using the RAII model. In fact we wrap the C entities in C++ object, taking care of correctly releasing them in the destructor.

This way we need not to handle resource deallocation explicitly (which can be a bit tedious when dealing with code that can throw exceptions in every moment).

raii1.cc (download)
#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <exception>

#include <cstdlib>
#include <cstring>
#include <cerrno>

extern "C" {
#include <unistd.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/uio.h>
}

class Lock{
    const int fd_;
    public:
    Lock(int fd) : fd_(fd) {
        int olderrno = errno;
	    int res = flock(fd_, LOCK_EX);
	    if (res<0){
	        perror(NULL);
	        throw "Cannot lock!";
	    }  
	    errno = olderrno;
	    std::cout <<"Locked"<< std::endl;
	}
	
	~Lock(){
	    flock(fd_, LOCK_UN);
	    std::cout <<"Unlocked"<< std::endl;
	}
};

class OldFile{
    int fd_;
    public:
    OldFile(const char* fname){
        int olderrno = errno;
        fd_ = open(fname, O_APPEND|O_WRONLY|O_CREAT, 0755);
        if (fd_<0){
            perror(NULL);
            errno = olderrno;
            throw "Unable to open file!";
        } else {
            errno = olderrno;
            std::cout <<"Opened"<< std::endl;
        }
    }
    
    int get_fd(){ return fd_; }
    
    ssize_t write(const char* s){
        std::cout << s << std::endl;
        std::cout << strlen(s) << std::endl;
        return ::write(fd_, s, strlen(s) );
    }
    
    ~OldFile(){
        std::cout <<"Closed"<< std::endl;
        close(fd_);
    }
};

void do_critical(const char* fname){
    static int counter=0;
    OldFile of(fname);
    Lock lock(of.get_fd());
    //do something
    of.write("// append...\n");
    if (counter%2){
        throw std::exception();
    }
    ++counter;
}

int main(){
    for(int i=0; i < 5; ++i){
        try{
            do_critical("easylock.cc");
        } catch (std::exception &e){
            std::cout << "Caught!" << std::endl;
        }
    }
    return 0;
}

back

xhtml 1.1 CSS 2.1 RSS 2.0
Made with a Mac Made with BBEdit Made with Brain

All documentation is under FDL and all source code is under BSD, unless differently stated.

24-mar-06