Joshua
open source statistical hierarchical phrase-based machine translation system
|
00001 #ifndef UTIL_SCOPED_H 00002 #define UTIL_SCOPED_H 00003 /* Other scoped objects in the style of scoped_ptr. */ 00004 00005 #include "util/exception.hh" 00006 #include <cstddef> 00007 #include <cstdlib> 00008 00009 namespace util { 00010 00011 class MallocException : public ErrnoException { 00012 public: 00013 explicit MallocException(std::size_t requested) throw(); 00014 ~MallocException() throw(); 00015 }; 00016 00017 void *MallocOrThrow(std::size_t requested); 00018 void *CallocOrThrow(std::size_t requested); 00019 00020 /* Unfortunately, defining the operator* for void * makes the compiler complain. 00021 * So scoped is specialized to void. This includes the functionality common to 00022 * both, namely everything except reference. 00023 */ 00024 template <class T, class Closer> class scoped_base { 00025 public: 00026 explicit scoped_base(T *p = NULL) : p_(p) {} 00027 00028 ~scoped_base() { Closer::Close(p_); } 00029 00030 void reset(T *p = NULL) { 00031 scoped_base other(p_); 00032 p_ = p; 00033 } 00034 00035 T *get() { return p_; } 00036 const T *get() const { return p_; } 00037 00038 T *operator->() { return p_; } 00039 const T *operator->() const { return p_; } 00040 00041 T *release() { 00042 T *ret = p_; 00043 p_ = NULL; 00044 return ret; 00045 } 00046 00047 protected: 00048 T *p_; 00049 00050 private: 00051 scoped_base(const scoped_base &); 00052 scoped_base &operator=(const scoped_base &); 00053 }; 00054 00055 template <class T, class Closer> class scoped : public scoped_base<T, Closer> { 00056 public: 00057 explicit scoped(T *p = NULL) : scoped_base<T, Closer>(p) {} 00058 00059 T &operator*() { return *scoped_base<T, Closer>::p_; } 00060 const T&operator*() const { return *scoped_base<T, Closer>::p_; } 00061 }; 00062 00063 template <class Closer> class scoped<void, Closer> : public scoped_base<void, Closer> { 00064 public: 00065 explicit scoped(void *p = NULL) : scoped_base<void, Closer>(p) {} 00066 }; 00067 00068 /* Closer for c functions like std::free and cmph cleanup functions */ 00069 template <class T, void (*clean)(T*)> struct scoped_c_forward { 00070 static void Close(T *p) { clean(p); } 00071 }; 00072 // Call a C function to delete stuff 00073 template <class T, void (*clean)(T*)> class scoped_c : public scoped<T, scoped_c_forward<T, clean> > { 00074 public: 00075 explicit scoped_c(T *p = NULL) : scoped<T, scoped_c_forward<T, clean> >(p) {} 00076 }; 00077 00078 class scoped_malloc : public scoped_c<void, std::free> { 00079 public: 00080 explicit scoped_malloc(void *p = NULL) : scoped_c<void, std::free>(p) {} 00081 00082 void call_realloc(std::size_t to); 00083 }; 00084 00085 /* scoped_array using delete[] */ 00086 struct scoped_delete_array_forward { 00087 template <class T> static void Close(T *p) { delete [] p; } 00088 }; 00089 // Hat tip to boost. 00090 template <class T> class scoped_array : public scoped<T, scoped_delete_array_forward> { 00091 public: 00092 explicit scoped_array(T *p = NULL) : scoped<T, scoped_delete_array_forward>(p) {} 00093 00094 T &operator[](std::size_t idx) { return scoped<T, scoped_delete_array_forward>::p_[idx]; } 00095 const T &operator[](std::size_t idx) const { return scoped<T, scoped_delete_array_forward>::p_[idx]; } 00096 }; 00097 00098 /* scoped_ptr using delete. If only there were a template typedef. */ 00099 struct scoped_delete_forward { 00100 template <class T> static void Close(T *p) { delete p; } 00101 }; 00102 template <class T> class scoped_ptr : public scoped<T, scoped_delete_forward> { 00103 public: 00104 explicit scoped_ptr(T *p = NULL) : scoped<T, scoped_delete_forward>(p) {} 00105 }; 00106 00107 void AdviseHugePages(const void *addr, std::size_t size); 00108 00109 } // namespace util 00110 00111 #endif // UTIL_SCOPED_H