nn::nlib::HandleMaker
を利用して、プロセス内で利用できる整数ハンドルを定義する方法を示します。
整数ハンドルでオブジェクトを間接的に参照する方法のメリットには以下のものがあります。
-
オブジェクトへのポインタを露出せずに利用させることができる。
-
クローズされたオブジェクトへのアクセスを防止できる。
-
多重クローズを行った場合でもクラッシュせずにエラーを報告できる。
nn::nlib::HandleMaker
クラスを利用すると、オブジェクトに対して整数ハンドルを割り当てるコードを簡単に記述することができます。
#include <memory>
class MyHandleBody {
public:
static const size_t N = 128;
public:
valid_ = false;
access_count_ = 0;
}
NLIB_ASSERT(!valid_);
}
NLIB_ASSERT(!valid_);
valid_ = true;
return 0;
}
if (!valid_) {
return EBADF;
}
valid_ = false;
return 0;
}
if (!valid_) {
return EBADF;
}
++access_count_;
nlib_printf(
"myhandle_access() from thread %d : access_count = %d\n",
id, access_count_);
return 0;
}
private:
bool valid_;
int access_count_;
};
std::unique_ptr<MyHandleBody> p(new (std::nothrow) MyHandleBody());
if (!p) return ENOMEM;
e = p->Initialize();
if (e != 0) {
return e;
}
e = maker.AttachHandleBody(handle, p.get());
(void)p->Finalize();
return e;
}
p.release();
return 0;
}
e = maker.GetHandleAccess(handle, &access);
if (e != 0) return e;
e = access->access_method();
return e;
}
e = maker.GetHandleAccess(handle, &access);
if (e != 0) return e;
e = access->Finalize();
return e;
}
bool SampleHandleMaker() {
int h;
const size_t kNumThread = 8;
e = myhandle_open(&h);
if (e != 0) return false;
auto thread_func = [](void* ph) {
int handle = (int)(intptr_t)ph;
for (int j = 0; j < 3; ++j) {
err = myhandle_access(handle);
if (err == EBADF) {
nlib_printf(
"myhandle_access() from thread %d, but handle already closed\n",
id);
break;
}
}
err = myhandle_close(handle);
};
for (size_t i = 0; i < kNumThread; ++i) {
NLIB_ASSERT(e == 0);
}
for (size_t i = 0; i < kNumThread; ++i) {
}
return true;
}
bool SampleMain(int, char**) { return SampleHandleMaker(); }
NLIB_MAINFUNC