简体   繁体   English

努力编写C API的线程安全的C ++包装器

[英]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. 我正在编写一个C ++的“线程安全”C ++包装器,而API本身并不是内部线程安全的。 I have tried to use RAII. 我曾尝试使用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, 要包装的C API如下,

 /* 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. 起初,我认为必须有free()而不是delete ,因为它是c api。 What you doing can give your resource-leak-free program, but not thread-safe. 你在做什么可以给你的资源泄漏程序,但不是线程安全的。 RAII is for avoiding leak of resources. RAII用于避免资源泄漏。 There is straightforward but inefficient way to wrap your API for thread safe to add static mutex in your RAII class. 有一种简单但低效的方法来包装您的API以保证线程安全,以便在您的RAII类中添加静态互斥。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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