问题描述
我已阅读 this 并在 Internet 上的许多其他地方进行了查找,但我找不到问题的答案。在 C++ 程序中,我有一个类 Clipboard
。此类正在监视 X11 选择事件,并在其更改时将选择内容提取到字符串成员中。对于大型选择,X11 使用“INCR 传输”机制。这个过程在上面的链接中有描述。获取大选择的内容时,我想检查选择大小是否超过某个限制(比如 20 兆字节),如果是,我不希望获取此选择以避免我的程序内存消耗不足.这大致是我目前的做法:
void Clipboard::fetchLargeSelectionContent()
{
/* We have received a property of type 'INCR' and are Now going to start
the read process
Variables ending with '_' are class' private members */
Atom clipboard = XInternAtom(display_,"CLIPBOARD",false);
Atom target = XInternAtom(display_,"UTF8_STRING",false);
unsigned long nItemsToRead = 0;
Atom typeReturned = None;
int formatReturned = 0;
unsigned long nItemsReturned = 0;
unsigned long nBytesRemaining = 0;
unsigned char* dataReturned = nullptr;
// We do not want selection to exceed 20 megabytes
std::string::size_type sizeLimit = 20 * 1024 * 1024;
bool maxSizeExceeded = false;
// Listen for property events on the requestor's(us) window
XSelectInput(display_,window_,PropertyChangeMask);
/* The xlib::getCurrentTime() function is defined in a separate header file
and returns the current X server time */
Time propertyReadTime = xlib::getCurrentTime();
/* Notify the selection owner that we are ready to receive the data
by deleting the property of type 'INCR' */
XDeleteProperty(display_,property_);
while (true)
{
XEvent event{};
XNextEvent(display_,&event);
if (event.type == PropertyNotify &&
event.xproperty.state == PropertyNewValue &&
event.xproperty.display == display_ &&
event.xproperty.window == window_ &&
event.xproperty.time >= propertyReadTime)
{
// Read zero bytes from the property just to get the size of its content
XGetwindowProperty(
display_,property_,false,target,&typeReturned,&formatReturned,&nItemsReturned,&nBytesRemaining,&dataReturned);
XFree(dataReturned);
dataReturned = nullptr;
if (nBytesRemaining == 0)
{
// Transfer completed
XDeleteProperty(display_,property_);
break;
}
nItemsToRead = nBytesRemaining;
propertyReadTime = xlib::getCurrentTime();
// Read the content and delete the property requesting a new data chunk
XGetwindowProperty(
display_,nItemsToRead,true,&dataReturned);
if (!maxSizeExceeded)
{
content_ += std::string(
reinterpret_cast<const char*>(dataReturned),nItemsReturned);
maxSizeExceeded = content_.size() > sizeLimit;
}
XFree(dataReturned);
dataReturned = nullptr;
}
}
if (maxSizeExceeded)
{
content_.clear();
std::string().swap(content_);
}
XSelectInput(display_,NoEventMask);
}
这种方法有效,但它有一个明显的缺点——即使在超过 sizeLimit
后仍会收到数据,只是不会写入 content_
。但是为什么我要接收我不打算存储和使用的数据?我需要以某种方式通知选择所有者我不再对接收新数据块感兴趣,并且它应该中止 INCR 传输过程。但我还没有找到一种方法来做到这一点。我试图简单地用 while (true)
替换 while (!maxSizeExceeded)
以在超过 sizeLimit
后立即中断循环。但似乎选择所有者仍在等待我的程序读取它发送的数据,因为我可以看到系统内存使用量显着增长,每次复制 500MB 文本数据。如果使用我示例中的方法,则不会发生这种情况(读取整个数据,如果数据太大则忽略它)。
那么,问题就在标题中——如何优雅地(正确地)中止增量数据传输的过程,有没有办法做到这一点?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)