C++ 中互斥锁的单例 class
Singleton class for mutex in c++
我正在努力让它工作,但似乎有一些我不完全理解的东西。
我在单个文件中有一个 multi-threaded 应用程序(2 classes 和我在其中创建线程和所有内容的真正的主程序)。我想分成 3 个文件。每个 class 一个(和他们的 header 一个)一个给 main.
我有几个 mutices 和一个 queue 可以在线程之间共享消息并随时锁定和解锁它们。
我想写一个单例 class 这样所有人都可以共享互斥量:
header:
#ifndef COMMONSINGLETON_H
#define COMMONSINGLETON_H
#include <mutex> // std::mutex
#include <queue>
class CommonSingleton{
private:
static std::mutex mutex_w_b;
//static std::mutex mutex_wifi_ok;
//static std::queue <std::string> queue_w_b;
public:
static CommonSingleton& getInstance();
std::mutex GetMutexWB();
//std::mutex GetMutexWiFiOk();
//std::queue <std::string> GetQueueWB();
private:
CommonSingleton() {};
CommonSingleton(CommonSingleton const&);
void operator=(CommonSingleton const&);
};
#endif
还有我的 .cpp 文件:
#include "commonsingleton.h"
static CommonSingleton& CommonSingleton::getInstance(){
static CommonSingleton instance;
return instance;
}
std::mutex CommonSingleton::GetMutexWB(){
return mutex_w_b;
}
/*std::mutex CommonSingleton::GetMutexWiFiOk(){
return mutex_wifi_ok;
}
std::queue <std::string> CommonSingleton::GetQueueWB(){
return queue_w_b;
}*/
我主要用这个来测试互斥体:
CommonSingleton::getInstance().GetMutexWB.lock();
不过现在评论出来了,就是为了搞清楚怎么编译。这是我得到的错误:
commonsingleton.cpp:4:54: error: cannot declare member function ‘static
CommonSingleton& CommonSingleton::getInstance()’ to have static linkage [-
fpermissive]
static CommonSingleton& CommonSingleton::getInstance(){
^
commonsingleton.cpp: In member function ‘std::mutex
CommonSingleton::GetMutexWB()’:
commonsingleton.cpp:9:12: error: use of deleted function
‘std::mutex::mutex(const std::mutex&)’
return mutex_w_b;
^
In file included from commonsingleton.h:5:0,
from commonsingleton.cpp:1:
/usr/include/c++/4.8/mutex:128:5: error: declared here
mutex(const mutex&) = delete;
我在这里做错了什么?
关键字static
在c++中有很多不同的含义。当您在 class 成员声明中使用它时,您将 class 成员声明为 static
,但是当您在 .cpp 文件中的 class 成员定义中使用它时,您将强制静态链接它(虽然它应该有外部链接才能在不同的翻译单元中使用)。
所以在 .cpp 文件中你应该改变
static CommonSingleton& CommonSingleton::getInstance(){
到
CommonSingleton& CommonSingleton::getInstance(){
您有一些编译器错误,如下所示:
首先,你不需要在函数定义中再次写static,因此在你的cpp中:
CommonSingleton& CommonSingleton::getInstance(){
static CommonSingleton instance;
return instance;
}
其次,std::mutex
删除了复制和移动构造函数,因此您不能 return 现有互斥体而不通过引用(或 const-ref)传递它,这会将您的 cpp 函数转换为:
std::mutex& CommonSingleton::GetMutexWB(){
return mutex_w_b;
}
std::mutex& CommonSingleton::GetMutexWiFiOk(){
return mutex_wifi_ok;
}
确保在声明中也更改这些 (.h)
更有用的单例是客户端程序不知道它是单例的单例。
这意味着如果您希望不进行重构,您可以在以后改变主意。
示例:
#include <mutex> // std::mutex
#include <iostream>
#include <thread>
#include <chrono>
#include <future>
// Note: This class is a singleton by internal implementation, not
// by interface. This separates the concerns of its function and its
// form, meaning client programs do not need to care.
//
class CommonSingleton{
using mutex_type = std::mutex;
using lock_type = std::unique_lock<mutex_type>;
private:
struct Impl {
mutex_type mutex_w_b;
lock_type get_lock() { return lock_type(mutex_w_b); }
};
static Impl& get_impl() {
static Impl impl {};
return impl;
}
public:
lock_type get_lock() {
return get_impl().get_lock();
}
};
// note - copyable
void foo(CommonSingleton singleton)
{
using namespace std::literals;
for(int i = 0 ; i < 10000 ; ++i) {
auto lock = singleton.get_lock();
std::cout << "foo\n";
lock.unlock();
std::this_thread::sleep_for(1ms);
}
}
void bar(CommonSingleton singleton)
{
using namespace std::literals;
for(int i = 0 ; i < 10000 ; ++i) {
auto lock = singleton.get_lock();
std::cout << "bar\n";
lock.unlock();
std::this_thread::sleep_for(1ms);
}
}
void baz(CommonSingleton singleton)
{
using namespace std::literals;
for(int i = 0 ; i < 10000 ; ++i) {
auto lock = singleton.get_lock();
std::cout << "baz\n";
lock.unlock();
std::this_thread::sleep_for(1ms);
}
}
int main()
{
// all using the same mutex in reality...
auto ffoo = std::async(std::launch::async, foo, CommonSingleton());
auto fbar = std::async(std::launch::async, bar, CommonSingleton());
auto fbaz = std::async(std::launch::async, baz, CommonSingleton());
ffoo.wait();
fbar.wait();
fbaz.wait();
}
您不需要那么多样板文件。你只需要一个功能:
std::mutex& getCommonMutex() {
static std::mutex m;
return m;
}
就是这样,您可以从任何地方调用此函数,它总是 return 对同一个互斥量的引用,该互斥量将在第一次调用时被初始化。
我正在努力让它工作,但似乎有一些我不完全理解的东西。
我在单个文件中有一个 multi-threaded 应用程序(2 classes 和我在其中创建线程和所有内容的真正的主程序)。我想分成 3 个文件。每个 class 一个(和他们的 header 一个)一个给 main.
我有几个 mutices 和一个 queue 可以在线程之间共享消息并随时锁定和解锁它们。
我想写一个单例 class 这样所有人都可以共享互斥量:
header:
#ifndef COMMONSINGLETON_H
#define COMMONSINGLETON_H
#include <mutex> // std::mutex
#include <queue>
class CommonSingleton{
private:
static std::mutex mutex_w_b;
//static std::mutex mutex_wifi_ok;
//static std::queue <std::string> queue_w_b;
public:
static CommonSingleton& getInstance();
std::mutex GetMutexWB();
//std::mutex GetMutexWiFiOk();
//std::queue <std::string> GetQueueWB();
private:
CommonSingleton() {};
CommonSingleton(CommonSingleton const&);
void operator=(CommonSingleton const&);
};
#endif
还有我的 .cpp 文件:
#include "commonsingleton.h"
static CommonSingleton& CommonSingleton::getInstance(){
static CommonSingleton instance;
return instance;
}
std::mutex CommonSingleton::GetMutexWB(){
return mutex_w_b;
}
/*std::mutex CommonSingleton::GetMutexWiFiOk(){
return mutex_wifi_ok;
}
std::queue <std::string> CommonSingleton::GetQueueWB(){
return queue_w_b;
}*/
我主要用这个来测试互斥体:
CommonSingleton::getInstance().GetMutexWB.lock();
不过现在评论出来了,就是为了搞清楚怎么编译。这是我得到的错误:
commonsingleton.cpp:4:54: error: cannot declare member function ‘static
CommonSingleton& CommonSingleton::getInstance()’ to have static linkage [-
fpermissive]
static CommonSingleton& CommonSingleton::getInstance(){
^
commonsingleton.cpp: In member function ‘std::mutex
CommonSingleton::GetMutexWB()’:
commonsingleton.cpp:9:12: error: use of deleted function
‘std::mutex::mutex(const std::mutex&)’
return mutex_w_b;
^
In file included from commonsingleton.h:5:0,
from commonsingleton.cpp:1:
/usr/include/c++/4.8/mutex:128:5: error: declared here
mutex(const mutex&) = delete;
我在这里做错了什么?
关键字static
在c++中有很多不同的含义。当您在 class 成员声明中使用它时,您将 class 成员声明为 static
,但是当您在 .cpp 文件中的 class 成员定义中使用它时,您将强制静态链接它(虽然它应该有外部链接才能在不同的翻译单元中使用)。
所以在 .cpp 文件中你应该改变
static CommonSingleton& CommonSingleton::getInstance(){
到
CommonSingleton& CommonSingleton::getInstance(){
您有一些编译器错误,如下所示:
首先,你不需要在函数定义中再次写static,因此在你的cpp中:
CommonSingleton& CommonSingleton::getInstance(){
static CommonSingleton instance;
return instance;
}
其次,std::mutex
删除了复制和移动构造函数,因此您不能 return 现有互斥体而不通过引用(或 const-ref)传递它,这会将您的 cpp 函数转换为:
std::mutex& CommonSingleton::GetMutexWB(){
return mutex_w_b;
}
std::mutex& CommonSingleton::GetMutexWiFiOk(){
return mutex_wifi_ok;
}
确保在声明中也更改这些 (.h)
更有用的单例是客户端程序不知道它是单例的单例。
这意味着如果您希望不进行重构,您可以在以后改变主意。
示例:
#include <mutex> // std::mutex
#include <iostream>
#include <thread>
#include <chrono>
#include <future>
// Note: This class is a singleton by internal implementation, not
// by interface. This separates the concerns of its function and its
// form, meaning client programs do not need to care.
//
class CommonSingleton{
using mutex_type = std::mutex;
using lock_type = std::unique_lock<mutex_type>;
private:
struct Impl {
mutex_type mutex_w_b;
lock_type get_lock() { return lock_type(mutex_w_b); }
};
static Impl& get_impl() {
static Impl impl {};
return impl;
}
public:
lock_type get_lock() {
return get_impl().get_lock();
}
};
// note - copyable
void foo(CommonSingleton singleton)
{
using namespace std::literals;
for(int i = 0 ; i < 10000 ; ++i) {
auto lock = singleton.get_lock();
std::cout << "foo\n";
lock.unlock();
std::this_thread::sleep_for(1ms);
}
}
void bar(CommonSingleton singleton)
{
using namespace std::literals;
for(int i = 0 ; i < 10000 ; ++i) {
auto lock = singleton.get_lock();
std::cout << "bar\n";
lock.unlock();
std::this_thread::sleep_for(1ms);
}
}
void baz(CommonSingleton singleton)
{
using namespace std::literals;
for(int i = 0 ; i < 10000 ; ++i) {
auto lock = singleton.get_lock();
std::cout << "baz\n";
lock.unlock();
std::this_thread::sleep_for(1ms);
}
}
int main()
{
// all using the same mutex in reality...
auto ffoo = std::async(std::launch::async, foo, CommonSingleton());
auto fbar = std::async(std::launch::async, bar, CommonSingleton());
auto fbaz = std::async(std::launch::async, baz, CommonSingleton());
ffoo.wait();
fbar.wait();
fbaz.wait();
}
您不需要那么多样板文件。你只需要一个功能:
std::mutex& getCommonMutex() {
static std::mutex m;
return m;
}
就是这样,您可以从任何地方调用此函数,它总是 return 对同一个互斥量的引用,该互斥量将在第一次调用时被初始化。