nlib
nn::nlib::HandleMaker< HBODY > Class Template Reference

A class supporting the implementation of handles with a 32-bit integer value. More...

#include "nn/nlib/HandleMaker.h"

Public Member Functions

 HandleMaker (HandleTable< HBODY > *ptr) noexcept
 Instantiates the object. A pointer to the table needs to be passed.
 
NLIB_CHECK_RESULT errno_t AttachHandleBody (int *handle, HBODY *body) noexcept
 Gets a handle that should be associated with the handle instance. More...
 
NLIB_CHECK_RESULT errno_t GetHandleAccess (int handle, HandleAccess< HBODY > *access) noexcept
 Obtains access from a handle to the handle instance. More...
 

Detailed Description

template<class HBODY>
class nn::nlib::HandleMaker< HBODY >

A class supporting the implementation of handles with a 32-bit integer value.

Template Parameters
HBODYHandle instance type.
Description
A class providing a mechanism to associate a 32-bit integer value (a handle) with an object (a handle instance). Using HandleMaker enables you to easily provide handles with the following features:
  • Access to the handle instance through the handle is thread safe.
  • Even if you use the handle after closing it (i.e. the handle is no longer valid), an error (generally, EBADF) can be returned without causing a crash.
  • The above features apply also for cases where the handle is closed from a different thread.
  • Since an integer value that acts as a handle will not be reused immediately, you can avoid unintentional access to the handle instance.
  • -1, 0, 1, 2, or 3 will not be assigned as a handle value.
Below is sample code to define a simple handle.
class MyHandleBody {
public:
// The following is used by <tt>HandleMaker</tt>.
static const size_t N = 128; // The maximum number of concurrent MyHandleBody objects.
void Lock() { nlib_mutex_lock(&lock_); } // Locks the resource.
void Unlock() { nlib_mutex_unlock(&lock_); } // Unlocks the resource.
bool IsHandleBodyEnabled() { return valid_; } // Whether available or not.
public:
MyHandleBody() {
valid_ = false;
nlib_mutex_init(&lock_);
}
~MyHandleBody() noexcept {
// No exception is allowed to be thrown within a destructor.
assert(!valid_);
}
errno_t Initialize(......) {
assert(!valid_);
{
// Open and other initialization.
}
valid_ = true;
return 0;
}
errno_t Finalize() {
// lock_ is locked.
if (!valid_) {
// Finalize() may have been executed while waiting for lock_.
// In addition, lock_ should be still able to be locked even after Finalize() is executed.
return EBADF;
}
{
// Close and other finalization.
}
valid_ = false;
return 0; // The handle will be released even if an error is returned.
}
errno_t access_method(......) {
// lock_ is locked.
if (!valid_) {
// Finalize() may have been executed while waiting for lock_.
return EBADF;
}
{
// Use of a handle instance.
}
return 0;
}
Private:
bool valid_;
nlib_mutex lock_;
// other data members ...
};
static nlib_ns::HandleTable<MyHandleBody> table_ = NLIB_HANDLETABLE_INITIALIZER;
// myhandle_open(), myhandle_close(), and myhandle_access() are thread safe.
errno_t myhandle_open(int* handle) {
MyHandleBody* p = new(std::nothrow) MyHandleBody();
if (!p) return ENOMEM;
e = p->Initialize()
if (nlib_is_error(e)) {
delete p;
return e;
}
// Assigns a handle to the handle instance.
e = maker.AttachHandleBody(handle, p);
if (nlib_is_error(e)) {
// No handle was available that could be assigned.
(void)p->Finalize();
delete p;
return e; // ENFILE
}
return 0;
}
errno_t myhandle_access(int handle, ......) {
e = maker.GetHandleAccess(handle, &access);
if (nlib_is_error(e)) return e; // EBADF
e = access->access_method(......);
return e;
}
errno_t myhandle_close(int handle) {
e = maker.GetHandleAccess(handle, &access);
if (nlib_is_error(e)) return e; // EBADF
access.DetachHandleBody();
e = access->Finalize();
return e;
}

Definition at line 87 of file HandleMaker.h.

Member Function Documentation

◆ AttachHandleBody()

template<class HBODY >
nn::nlib::HandleMaker< HBODY >::AttachHandleBody ( int *  handle,
HBODY *  body 
)
noexcept

Gets a handle that should be associated with the handle instance.

Parameters
[out]handlePointer to the handle associated with body.
[in]bodyHandle instance to be associated with the handle.
Return values
0Success.
ENFILENo handle is available that can be assigned.

Definition at line 191 of file HandleMaker.h.

◆ GetHandleAccess()

template<class HBODY >
nn::nlib::HandleMaker< HBODY >::GetHandleAccess ( int  handle,
HandleAccess< HBODY > *  access 
)
noexcept

Obtains access from a handle to the handle instance.

Parameters
[in]handleHandle obtained with AttachHandleBody().
[out]accessAccessor to an instance corresponding to the handle.
Return values
0Success.
EBADFThe handle is not valid.

Definition at line 258 of file HandleMaker.h.


The documentation for this class was generated from the following files: