简体   繁体   中英

Effort to write a thread-safe C++ wrapper of C API

I am writing a 'thread-safe' C++ wrapper of C API, while the API itself is NOT internally thread safe. I have tried to use RAII.

I would like to know, is my implementation correct? and whether it is thread safe. I appreciate any comments on my code. Thanks in advance!

The C API to be wrapped is as follows,

 /* an data structure which represents a connection proxy to the logger: */
struct cLog_Logger;

/* connect the logger, and returns a handle to it: */
cLog_Logger* cLog_connect();

/* appends a zero terminated string to the log: */
void cLog_write(cLog_Logger* logger, const char* message);

/* closes the connection with the logger: */
void cLog_close(cLog_Logger* logger);

My implementation of the wrapper is as follows:

    class LoggerWrapper{

    public:
        LoggerWrapper(){              //constructor
            cLog= cLog_connect();
        }

        void log(const std::string &message){    //entry point
            cLog_write(cLog, message);
            cLog_close(cLog);
            }

        ~LoggerWrapper(){        //destructor
            delete cLog;
        }
    protected:
         cLog_Logger *cLog;
}

Thanks!

I think you need to change the implementation like this:

class LoggerWrapper{

public:
    LoggerWrapper(){              //constructor
        cLog= cLog_connect();
    }

    void log(const std::string &message){    //entry point
        cLog_write(cLog, message);
        }

    ~LoggerWrapper(){        //destructor
        cLog_close(cLog);
        delete cLog;
    }
protected:
     cLog_Logger *cLog;
} ;

This allows you to write code like this:

LoggerWrapper logger ;
logger.log("Something") ;
logger.log("Something else) ;

so make more than one log with the same object; otherwise the first call closes the logger and the object is useless. Is this what you want?

Then there is the second question: what do you mean by thread safety? Do you want to make logs on the same object from different threads?

Then you can add a mutex and a lock guard inside log function like this:

class LoggerWrapper{

public:
    LoggerWrapper(){              //constructor
        cLog= cLog_connect();
    }

    void log(const std::string &message){    //entry point
        std::lock_guard<std::mutex> guard(mutex);
        cLog_write(cLog, message);
        }

    ~LoggerWrapper(){        //destructor
        cLog_close(cLog);
        delete cLog;
    }
protected:
     cLog_Logger *cLog;
     std::mutex mutex ;
} ;

Short answer: no it's not. At first, I think there must be free() instead of delete , because it's c api. What you doing can give your resource-leak-free program, but not thread-safe. RAII is for avoiding leak of resources. There is straightforward but inefficient way to wrap your API for thread safe to add static mutex in your RAII class.

#include <mutex>

class LoggerWrapper{

public:
    LoggerWrapper() : l(globalLock);
    {              //constructor
        cLog= cLog_connect();
    }

    void log(const std::string &message){    //entry point
        cLog_write(cLog, message);
        cLog_close(cLog);
        }

    ~LoggerWrapper(){        //destructor
        free(cLog); // I think here must be free(), but not sure
    }
protected:
    cLog_Logger *cLog;
    static std::mutex globalLock;
    std::lock_guard<std::mutex> l;
}

std::mutex LoggerWrapper::globalLock;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM