我的场景:一台服务器和一些客户端(虽然不多).服务器一次只能响应一个客户端,因此必须排队.我正在使用互斥(boost::interprocess::interprocess_mutex)执行此操作,包含在boost::interprocess::scoped_lock.
问题是,如果一个客户端在持有互斥锁时意外死亡(即没有析构函数运行),则其他客户端遇到麻烦,因为他们正在等待该互斥锁.我考虑过使用定时等待,所以如果我的客户端等待,比如20秒并且没有得到互斥锁,那么它就会继续与服务器通信.
这种方法的问题:1)它每次都这样做.如果它处于循环中,不断与服务器通信,则需要每次都等待超时.2)如果有三个客户端,并且其中一个客户端在持有互斥锁时死亡,则另外两个客户端将等待20秒并同时与服务器通信 - 这正是我试图避免的.
所以,我怎么能对客户说,"嘿那里,似乎这个互斥体已被抛弃,取得它的所有权"?
这是一个令人尴尬的问题,但即使是boost.interprocess提供的精心编写的文档也不足以让我弄清楚如何做到这一点.
我有一个cached_adaptive_pool分配器实例,我想用它来构造一个对象,传递构造函数参数:
struct Test {
Test(float argument, bool flag);
Test();
};
// Normal construction
Test obj(10, true);
// Normal dynamic allocation
Test* obj2 = new Test(20, false);
typedef managed_unique_ptr<
Test, boost::interprocess::managed_shared_memory>::type unique_ptr;
// Dynamic allocation where allocator_instance == cached_adaptive_pool,
// using the default constructor
unique_ptr obj3 = allocator_instance.allocate_one()
// As above, but with the non-default constructor
unique_ptr obj4 = allocator_instance ... ???
Run Code Online (Sandbox Code Playgroud)
这可能是我在如何使用分配器对象方面的失败.但在任何情况下,我都看不到如何使用这个特定的分配器,使用cached_adaptive_pool中指定的接口将构造函数参数传递给我的对象.
cached_adaptive_pool有方法:void construct(const pointer & ptr, const_reference v)但我不明白这意味着什么,我找不到使用它的例子.
我的头一整天都在模板中游泳,所以即使答案很明显,也会非常感激.
我有一个多线程服务器应用程序,需要在某些共享内存上进行互斥锁定.
共享内存基本上是sTL地图等.
很多时候我只是从地图上读书.但是,我还需要偶尔添加它.
例如typedef std :: map MessageMap; MessageMap msgmap; boost:shared_mutex access_;
void ProcessMessage(Message* message)
{
// Access message... read some stuff from it message->...
UUID id = message->GetSessionID();
// Need to obtain a lock here. (shared lock? multiple readers)
// How is that done?
boost::interprocess::scoped_lock(access_);
// Do some readonly stuff with msgmap
MessageMap::iterator it = msgmap.find();
//
// Do some stuff...
// Ok, after all that I decide that I need to add an entry to the map.
// …Run Code Online (Sandbox Code Playgroud) 我对将std::string密钥和大struct值放入容器之类所涉及的堆和按值与引用语义有点混淆boost::interprocess::map.
这是我的情况,以及我正在使用的一些typedef:
typedef std::string AreaKeyType;
typedef DATA_AREA_DESC AreaMappedType; // DATA_AREA_DESC is a big struct.
typedef std::pair<const AreaKeyType, AreaMappedType> AreaValueType;
typedef boost::interprocess::allocator<AreaValueType, boost::interprocess::managed_shared_memory::segment_manager> AreaShmemAllocator;
typedef boost::interprocess::map<AreaKeyType, AreaMappedType, std::less<AreaKeyType>, AreaShmemAllocator> AreaMap;
Run Code Online (Sandbox Code Playgroud)
这是我如何插入AreaValueType(这是std :: pair的typedef):
AreaValueType A(areaKey, arearec);
anAreaMap->insert(A);
Run Code Online (Sandbox Code Playgroud)
我相信上面的代码将我在本地(非共享内存)堆栈上的std :: pair复制到共享内存区域.我可以在boost :: interprocess :: map中获取该共享内存区域的句柄,还是仅限于将该记录整回并整个存储?(换句话说,我可以将类似结构的东西存储到boost进程间映射中,然后更新该记录中的单个字节,或者我必须通过替换DATA_AREA_DESC结构中的所有字节来更新整个记录,全新字节).
进一步澄清:
我有一个普通的旧ANSI C DLL导出api,内部使用C++和Boost :: interprocess :: map.该函数应该在地图中创建一个项目,然后返回一个句柄.如何在boost :: interprocess :: map中插入一些东西,然后将一个句柄返回给非C++用户,最好是强制转换为void*或者unsigned long?我所能做的就是通过查找std :: string键值从共享内存中获取内容,并将新记录写入内存.我希望能够保持对共享内存对象的引用.
如果我不能直接这样做,我将如何间接地做到这一点?我想我可以保持一个非共享内存的std ::向量,并分配一个非共享内存的std :: string持有areaKey,这是一个std :: string的值,然后做的投void*项目返回std::string然后使用它从共享内存区域中获取记录.对于一些如此基本的东西来说,这似乎都是非常必要的工作.也许boost :: interprocess …
我想在线程之间共享数据,并在最后一个用户完成后自动删除它.这似乎在大多数情况下boost::interprocess::shared_ptr在一个boost::fixed_managed_shared_memory段中使用:但并非总是如此.
那么,是boost::interprocess::shared_ptr线程(和进程间) - 安全吗?
如果我在固定地址使用我的共享内存(我很确定这在我的64位(井,48位)地址空间中是可以的),是否可以使用普通boost::shared_ptr(这是线程安全)而不是?
一些澄清:
我使用的指针类型是plain void*,(我的共享内存映射到固定地址).
线程安全的问题是关于引用计数 - 即,是否允许同时复制/销毁在不同进程中同一事物的共享指针.不能访问不同线程中的相同共享指针,也不能访问指针.
我想用它boost::interprocess::file_lock来确保x进程写入目录的文件在完成之前P1不会被进程读取P2.要做到这一点,我想在编写P1文件boost::interprocess::file_lock时锁定文件,然后在文件完成时将其解锁.然后P2可以跳过(并返回)任何被锁定的文件.
我遇到的问题是它似乎boost::interprocess::file_lock只允许你锁定存在的文件.但是,如果我首先创建文件,然后锁定它,那么就存在竞争条件:
P1 创建文件P2 注意到文件并开始阅读P1 锁定文件P1 写一些数据P2读取一些数据,到达终点,最后只得到部分P1输出.所以我想做的就是创建一个文件,并在创建文件后立即将其锁定.有没有办法使用boost::interprocess::file_lock?
请考虑以下结构:
struct ThingThatWillGoInSharedMemory {
boost::optional<int> opt_value;
};
Run Code Online (Sandbox Code Playgroud)
我正在使用boost :: interprocess来创建共享内存区域.我对boost :: optional的理解是它是一个有区别的联合而不是一个可空的指针.作为反例,使用堆的std :: map和std :: vector之类的东西需要一个显式的分配器来在进程间内存中使用它们,但是boost :: optional,我相当肯定不使用堆并且相当于写作:
struct ThingThatWillGoInSharedMemory {
bool value_initialised;
int value;
}
Run Code Online (Sandbox Code Playgroud)
所以它可以开箱即用.如果有人确认这一点,我会很高兴 - 我没有看到在boost :: optional文档中明确提到了进程间案例,只是暗示了.
我已经阅读了一些相关内容boost::interprocess::file_lock,它似乎做了我想要做的事情(支持共享和独占锁定,并在进程崩溃或退出时解锁)。
但我不确定的一件事是它对文件有什么作用?例如,我可以使用 0 字节长的文件吗?boost::interprocess里面写东西吗?或者系统只关心它的存在吗?
我现在已经使用了boost::interprocess一段时间来可靠地内存映射文件并写入文件,现在我需要进行多进程并确保对此文件的读取和写入受到保护;file_lock似乎是可行的方法,我只是想知道我现在是否需要添加另一个文件来用作互斥体。
提前致谢
有一个简单的方法吗?我尝试过以下方法:
typedef allocator<char,managed_shared_memory::segment_manager>
CharAllocator;
typedef boost::container::basic_string<char, std::char_traits<char>, CharAllocator>
my_basic_string;
std::string s(my_basic_string);
Run Code Online (Sandbox Code Playgroud) 我想读取并从txt文件中删除第一行(没有复制,这是一个巨大的文件).
我已经阅读了网络,但每个人都只是将所需的内容复制到一个新文件中.我做不到.
低于第一次尝试.由于没有删除行,此代码将被置于循环中.如果代码将在每个开头删除第一行文件,代码将到达结尾.
#include <iostream>
#include <string>
#include <fstream>
#include <boost/interprocess/sync/file_lock.hpp>
int main() {
std::string line;
std::fstream file;
boost::interprocess::file_lock lock("test.lock");
while (true) {
std::cout << "locking\n";
lock.lock();
file.open("test.txt", std::fstream::in|std::fstream::out);
if (!file.is_open()) {
std::cout << "can't open file\n";
file.close();
lock.unlock();
break;
}
else if (!std::getline(file,line)) {
std::cout << "empty file\n"; //
file.close(); // never
lock.unlock(); // reached
break; //
}
else {
// remove first line
file.close();
lock.unlock();
// do something with line
}
}
}
Run Code Online (Sandbox Code Playgroud) c++ ×10
boost ×7
stdstring ×2
allocator ×1
boost-thread ×1
concurrency ×1
file-locking ×1
fstream ×1
getline ×1
interprocess ×1
templates ×1
visual-c++ ×1