libfoedus-core
FOEDUS Core Library
foedus::UninitializeGuard Class Reference

Calls Initializable::uninitialize() automatically when it gets out of scope. More...

Detailed Description

Calls Initializable::uninitialize() automatically when it gets out of scope.

NOT A SILVER BULLET! This is a scope guard object to help release Initializable objects, but there are inherent difficulties to handle errors out of uninitialization. eg: http://stackoverflow.com/questions/159240/raii-vs-exceptions

The only correct solution is for every code to make sure calling uninitialize() explicitly and handling the returned ErrorStack responsively. This object is just an imperfect safety net.

Definition at line 220 of file initializable.hpp.

#include <initializable.hpp>

Public Types

enum  Policy { kAbortIfNotExplicitlyUninitialized = 0, kAbortIfUninitializeError, kWarnIfUninitializeError, kSilent }
 Defines the behavior of this scope guard. More...
 

Public Member Functions

 UninitializeGuard (Initializable *target, Policy policy=kAbortIfUninitializeError)
 
 ~UninitializeGuard ()
 

Member Enumeration Documentation

Defines the behavior of this scope guard.

Enumerator
kAbortIfNotExplicitlyUninitialized 

Terminates the entire program if uninitialize() wasn't called when it gets out of scope.

This is used to look for coding issues where we overlook chances of early returns. Although this is stringent, recommended.

kAbortIfUninitializeError 

Automatically calls if uninitialize() wasn't called when it gets out of scope, and terminates the entire program when uninitialize() actually returns an error.

In either case, we warn about the lack of explicit uninitialize() call in debug log. This is the default.

kWarnIfUninitializeError 

Automatically calls if uninitialize() wasn't called when it gets out of scope, and just complains when uninitialize() actually returns an error in debug log.

kSilent 

Automatically calls if uninitialize() wasn't called when it gets out of scope, and does nothing even when uninitialize() actually returns an error in debug log.

NOT RECOMMENDED.

Definition at line 225 of file initializable.hpp.

225  {
249  kSilent,
250  };
Automatically calls if uninitialize() wasn't called when it gets out of scope, and just complains whe...
Automatically calls if uninitialize() wasn't called when it gets out of scope, and does nothing even ...
Terminates the entire program if uninitialize() wasn't called when it gets out of scope...
Automatically calls if uninitialize() wasn't called when it gets out of scope, and terminates the ent...

Constructor & Destructor Documentation

foedus::UninitializeGuard::UninitializeGuard ( Initializable target,
Policy  policy = kAbortIfUninitializeError 
)
inline

Definition at line 251 of file initializable.hpp.

252  : target_(target), policy_(policy) {}
foedus::UninitializeGuard::~UninitializeGuard ( )

Definition at line 29 of file initializable.cpp.

References ASSERT_ND, foedus::ErrorStack::is_error(), foedus::Initializable::is_initialized(), kAbortIfNotExplicitlyUninitialized, kAbortIfUninitializeError, kSilent, kWarnIfUninitializeError, foedus::print_backtrace(), and foedus::Initializable::uninitialize().

29  {
30  if (target_->is_initialized()) {
31  if (policy_ != kSilent) {
32  LOG(ERROR) << "UninitializeGuard has found that " << typeid(*target_).name()
33  << "#uninitialize() was not called when it was destructed. This is a BUG!"
34  << " We must call uninitialize() before destructors!";
36  }
37  if (policy_ == kAbortIfNotExplicitlyUninitialized) {
38  LOG(FATAL) << "FATAL: According to kAbortIfNotExplicitlyUninitialized policy,"
39  << " we abort the program" << std::endl;
40  ASSERT_ND(false);
41  std::abort();
42  } else {
43  // okay, call uninitialize().
44  ErrorStack error = target_->uninitialize();
45  // Note that this is AFTER uninitialize(). "target_" might be Engine
46  // or DebuggingSupports. So, we might not be able to use glog any more.
47  // Thus, we must use stderr in this case.
48  if (error.is_error()) {
49  switch (policy_) {
51  std::cerr << "FATAL: UninitializeGuard encounters an error on uninitialize()."
52  << " Aborting as we can't propagate this error appropriately."
53  << " error=" << error << std::endl;
54  ASSERT_ND(false);
55  std::abort();
56  break;
58  std::cerr << "WARN: UninitializeGuard encounters an error on uninitialize()."
59  << " We can't propagate this error appropriately. Not cool!"
60  << " error=" << error << std::endl;
61  break;
62  default:
63  // warns nothing. this policy is NOT recommended
64  ASSERT_ND(policy_ == kSilent);
65  }
66  } else {
67  if (policy_ != kSilent) {
68  std::cerr << "But, fortunately uninitialize() didn't return errors, phew"
69  << std::endl;
70  }
71  }
72  }
73  }
74 }
Automatically calls if uninitialize() wasn't called when it gets out of scope, and just complains whe...
Automatically calls if uninitialize() wasn't called when it gets out of scope, and does nothing even ...
Terminates the entire program if uninitialize() wasn't called when it gets out of scope...
Automatically calls if uninitialize() wasn't called when it gets out of scope, and terminates the ent...
virtual ErrorStack uninitialize()=0
An idempotent method to release all resources of this object, if any.
std::string print_backtrace()
Prints out backtrace.
Definition: assert_nd.cpp:37
#define ASSERT_ND(x)
A warning-free wrapper macro of assert() that has no performance effect in release mode even when 'x'...
Definition: assert_nd.hpp:72
virtual bool is_initialized() const =0
Returns whether the object has been already initialized or not.

Here is the call graph for this function:


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