Skip to content

Similar to std::unique_ptr but generalises the idea of pointer to generic resource

Notifications You must be signed in to change notification settings

jt-9/raii-unique_rc

Repository files navigation

unique_rc

raii::unique_rc is a small open-source C++ library which provides RAII wrapper for generic resource - anything that needs to be acquired, used, and eventually released.

If you like this project, please consider donating to one of the funds that help victims of the war in Ukraine: https://www.stopputin.net/.

About:

The idea behind raii::unique_rc is similar to std::unique_ptr in providing automatic and exception-safe deallocation of dynamically allocated resource be it a memory, file descriptors, file handles, events, sockets, COM objects, GDI objects, etc.

The key difference is a requirement for 'deallocator', a functional object which deallocates resource, to provide what is viewed as invalid value. This approach is described in Kenny Kerr's artcle Windows with C++ - C++ and the Windows API. raii::unique_rc provides similar interface to std::unique_ptr, but unlike latter, which compares against pointer(), raii::unique_rc requires deallocator to specify an invalid type and value e.g. INVALID_HANDLE_VALUE, INVALID_SOCKET, etc.

Documentation:

To be added

Features:

  • Interface similar to std::unique_ptr, with invalid type and invalid value defined in deallocator. This simplifies work with handles typically allocated via API function such as fopen, CreateFile, etc.
  • Small code size consisting of just several files unique_rc.hpp, unique_ptr.hpp, defs.hpp and deallocators.
  • Clean warning-free codebase even on high warning levels such as -Wall -Wextra -pedantic.
  • Specialised raii::unique_ptr - equivalent to std::unique_ptr, derived from raii::unique_rc.

Examples:

1. File descriptor

#include "unique_rc.hpp"
#include "stdio_fclose.hpp"

#include <stdio.h>

int main() {
  raii::unique_rc<FILE *, raii::stdio_fclose> streamRC{ fopen("/tmp/test.txt", "r+") };
  if (streamRC) {
    // Do work here...
    // Use streamRC.get() to get file descriptor
  }
}

with stdio fclose deallocator

struct stdio_fclose
{
  constexpr stdio_fclose() noexcept = default;

  [[nodiscard]] static constexpr std::nullptr_t invalid() noexcept { return nullptr; }

  void operator()(FILE *h) const noexcept { fclose(h); }
};

2. CreateFile

#include "unique_rc.hpp"
#include "windows_close_handle.hpp"

#include <windows.h>

int main() {
  raii::unique_rc<HANDLE, 
      raii::close_handle_invalid_handle_value<HANDLE>> myFile{ CreateFile(/* params */) };
  if (myFile) {
    // Do your work...
    // Use myFile.get() to get file HANDLE
  }
}

with CloseHandle deallocator

template<typename Handle = HANDLE>
  requires std::convertible_to<Handle, HANDLE>
struct close_handle_invalid_handle_value
{
  constexpr close_handle_invalid_handle_value() noexcept = default;

  [[nodiscard]] static constexpr Handle invalid() noexcept { return INVALID_HANDLE_VALUE; }

  void operator()(Handle h) const noexcept { CloseHandle(h); }
};

3. raii::unique_ptr to manage dynamic memory

#include "unique_ptr.hpp"

int main() {
  raii::unique_ptr<int> intPtr = raii::make_unique<int>(23);
  // Work with pointer, use *intPtr to get a value
}

Acknowledgments

About

Similar to std::unique_ptr but generalises the idea of pointer to generic resource

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published