我正在努力让这项工作得以实现,但似乎有些事情我不能完全理解。
我在一个文件中有一个多线程应用程序(2个类和我创建线程和所有内容的真正主要部分)。我想分成3个文件。每个类一个(带有标题),一个用于主。
我有几个mutices和一个队列来在线程之间共享消息并随时锁定和解锁它们。
我想写一个单例类,所以它们都可以共享互斥锁:
头:
#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;
我在这里做错了什么?
答案 0 :(得分:3)
你不需要那么多样板文件。你只需要一个功能:
std::mutex& getCommonMutex() {
static std::mutex m;
return m;
}
就是这样,你可以从任何地方调用这个函数,它总是会返回对同一个互斥锁的引用,这个互斥锁将在它第一次被调用时被初始化。
答案 1 :(得分:2)
您有一些编译器错误如下:
首先,您不需要在函数定义中再次编写静态,因此在您的cpp中:
CommonSingleton& CommonSingleton::getInstance(){
static CommonSingleton instance;
return instance;
}
其次,std::mutex
删除了复制和移动构造函数,因此您无法通过引用(或const-ref)传递现有的互斥锁,而是将cpp函数转换为:
std::mutex& CommonSingleton::GetMutexWB(){
return mutex_w_b;
}
std::mutex& CommonSingleton::GetMutexWiFiOk(){
return mutex_wifi_ok;
}
确保您也在声明中更改了这些(.h)
答案 2 :(得分:2)
更有用的单例是客户端程序不知道它是单例的单例。
这意味着如果您希望不进行重构,您可以在以后改变主意。
示例:
#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();
}
答案 3 :(得分:1)
关键字static
在c ++中有许多不同的含义。当你在类成员声明中使用它时,你将类成员声明为static
,但是当你在.cpp文件中的类成员定义中使用它时,你强制它上面的静态链接(虽然它应该有外部链接可用于不同的翻译单位)。
所以在.cpp文件中你应该改变
static CommonSingleton& CommonSingleton::getInstance(){
到
CommonSingleton& CommonSingleton::getInstance(){