gpt4 book ai didi

c++ - RAII 范围内的分配

转载 作者:行者123 更新时间:2023-11-30 01:17:24 25 4
gpt4 key购买 nike

问题

如何在 RAII 作用域内初始化一个对象,并在该作用域外使用它?

背景

  • 我有一个全局锁,可以用 lock()unlock() 调用。

  • 我有一个类型,LockedObject,只有在全局锁锁定时才能初始化。

  • 我有一个函数,use_locked(LockedObject &locked_object),需要在全局锁解锁的情况下调用。

使用场景是

lock();
LockedObject locked_object;
unlock();
use_locked(locked_object);

RAII

由于各种原因,我搬到了全局锁的RAII封装。我想在任何地方都使用它,主要是因为创建 LockedObject 可能会因异常而失败。

问题是

{
GlobalLock global_lock;
LockedObject locked_object;
}
use_locked(locked_object);

失败,因为 locked_object 是在内部范围内创建的。

例子

设置(大部分不重要):

#include <assert.h> 
#include <iostream>

bool locked = false;

void lock() {
assert(!locked);
locked = true;
}

void unlock() {
assert(locked);
locked = false;
}

class LockedObject {
public:
LockedObject(int i) {
assert(locked);
std::cout << "Initialized: " << i << std::endl;
}
};

void use_locked(LockedObject locked_object) {
assert(!locked);
}

class GlobalLock {
public:
GlobalLock() {
lock();
}

~GlobalLock() {
unlock();
}
};

原始的,非 RAII 方法:

void manual() {
lock();
LockedObject locked_object(123);
unlock();
use_locked(locked_object);
}

损坏的 RAII 方法:

/*
void raii_broken_scoping() {
{
GlobalLock global_lock;

// Initialized in the wrong scope
LockedObject locked_object(123);
}
use_locked(locked_object);
}
*/

/*
void raii_broken_initialization() {
// No empty initialization
// Alternatively, empty initialization requires lock
LockedObject locked_object;
{
GlobalLock global_lock;
locked_object = LockedObject(123);
}
use_locked(locked_object);
}
*/

还有一个 main 函数:

int main(int, char **) {
manual();
// raii_broken_scoping();
// raii_broken_initialization;
}

对于它的值(value),在 Python 中我会这样做:

with GlobalLock():
locked_object = LockedObject(123)

我想要那个的等价物。我在一个答案中提到了我目前的解决方案,但感觉很笨拙。


要执行的具体(但已简化)代码如下。使用我当前基于 lambda 的调用:

boost::python::api::object wrapped_object = [&c_object] () {
GIL lock_gil;
return boost::python::api::object(boost::ref(c_object));
} ();

auto thread = std::thread(use_wrapped_object, c_object);

class GIL {
public:
GIL();
~GIL();

private:
GIL(const GIL&);
PyGILState_STATE gilstate;
};
GIL::GIL() {
gilstate = PyGILState_Ensure();
}

GIL::~GIL() {
PyGILState_Release(gilstate);
}

boost::python::api::object必须使用 GIL 创建并且线程必须在没有 GIL 的情况下创建. PyGILState 结构和函数调用都是由 CPython 的 C API 提供给我的,因此我只能将它们包装起来。

最佳答案

在堆上分配你的对象并使用一些指针:

std::unique_ptr<LockedObject> locked_object;
{
GlobalLock global_lock;
locked_object.reset(new LockedObject());
}
use_locked(locked_object);

关于c++ - RAII 范围内的分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24477791/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com