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;
}