- 主题:一个小小的析构"陷阱"
谷歌PDFium库不能多线程调用,需要加全局锁。pdf doc析构时也要加锁。
ScopedFPDFDocument是个std::unique_ptr<>。
static std::mutex g_pdfLock;
CMyPDFProcessor {
public:
~CMyPDFProcessor();
private:
ScopedFPDFDocument m_pdfDoc;
}
这种写法不行,因为锁到了右花括号就析构,而编译器自动加的析构m_pdfDoc的代码在花括号之后:
CMyPDFProcessor::~CMyPDFProcessor(){
std::lock_guard<std::mutex> guard{g_pdfLock};
}
改为这种写法:
CMyPDFProcessor::~CMyPDFProcessor(){
{
std::lock_guard<std::mutex> guard{g_pdfLock};
ScopedFPDFDocument pdfDoc = std::move(m_pdfDoc);
}
}
或者:
CMyPDFProcessor::~CMyPDFProcessor(){
std::lock_guard<std::mutex> guard{g_pdfLock};
m_pdfDoc.reset();
}
--
FROM 114.254.46.*
PDFium依赖的其他库太多,不是每个库都能保证线程安全(即使每个线程操作不同的pdf doc句柄),所以导致PDFium不是线程安全的
ScopedFPDFDocument最后是std::unique_ptr<>的析构调用custom deleter,执行FPDF_CloseDocument(doc),这个就会引用PDFium内部的数据,不是线程安全的。
https://groups.google.com/g/pdfium/c/HeZSsM_KEUk?pli=1
【 在 DoorWay 的大作中提到: 】
: 析构也要加锁,这库设计的怎么这么别扭
--
FROM 114.254.46.*
支持多线程有个粒度的吧
比如A调用B, B调用C
可以在C这一层直接支持多线程随便调用,
也可以在C这层只支持每个线程对应一个独立的实例,然后在B这层支持多线程随便调用
【 在 DoorWay 的大作中提到: 】
: 不懂就问,
: 这玩意儿不是要设计成编译器那样,不管多复杂,facade模式,对外的接口单一好吗?难道调用者还要关心一个Doc实例,有多少线程在持有吗?
: MFC时代的术语,SDI,Single Document Interface,单文档接口,处理这种情况,打开后独占,不行吗?
--
FROM 114.254.46.*