• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

ink_memory.h

Go to the documentation of this file.
00001 /** @file
00002 
00003   Memory allocation routines for libts.
00004 
00005   @section license License
00006 
00007   Licensed to the Apache Software Foundation (ASF) under one
00008   or more contributor license agreements.  See the NOTICE file
00009   distributed with this work for additional information
00010   regarding copyright ownership.  The ASF licenses this file
00011   to you under the Apache License, Version 2.0 (the
00012   "License"); you may not use this file except in compliance
00013   with the License.  You may obtain a copy of the License at
00014 
00015       http://www.apache.org/licenses/LICENSE-2.0
00016 
00017   Unless required by applicable law or agreed to in writing, software
00018   distributed under the License is distributed on an "AS IS" BASIS,
00019   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020   See the License for the specific language governing permissions and
00021   limitations under the License.
00022  */
00023 #ifndef _ink_memory_h_
00024 #define _ink_memory_h_
00025 
00026 #include <ctype.h>
00027 #include <string.h>
00028 #include <strings.h>
00029 
00030 #include "ink_config.h"
00031 
00032 #if HAVE_UNISTD_H
00033 #include <unistd.h>
00034 #endif
00035 
00036 #if HAVE_SYS_TYPES_H
00037 #include <sys/types.h>
00038 #endif
00039 
00040 #if HAVE_SYS_UIO_H
00041 #include <sys/uio.h>
00042 #endif
00043 
00044 #if HAVE_SYS_MMAN_H
00045 #include <sys/mman.h>
00046 #endif
00047 
00048 #if TS_HAS_JEMALLOC
00049 #include <jemalloc/jemalloc.h>
00050 /* TODO: Should this have a value ? */
00051 #define ATS_MMAP_MAX 0
00052 #else
00053 #if HAVE_MALLOC_H
00054 #include <malloc.h>
00055 #define ATS_MMAP_MAX M_MMAP_MAX
00056 #endif // ! HAVE_MALLOC_H
00057 #endif // ! TS_HAS_JEMALLOC
00058 
00059 #ifndef MADV_NORMAL
00060 #define MADV_NORMAL 0
00061 #endif
00062 
00063 #ifndef MADV_RANDOM
00064 #define MADV_RANDOM 1
00065 #endif
00066 
00067 #ifndef MADV_SEQUENTIAL
00068 #define MADV_SEQUENTIAL 2
00069 #endif
00070 
00071 #ifndef MADV_WILLNEED
00072 #define MADV_WILLNEED 3
00073 #endif
00074 
00075 #ifndef MADV_DONTNEED
00076 #define MADV_DONTNEED 4
00077 #endif
00078 
00079 #ifdef __cplusplus
00080 extern "C" {
00081 #endif                          /* __cplusplus */
00082 
00083   typedef struct iovec IOVec;
00084 
00085   void *  ats_malloc(size_t size);
00086   void *  ats_calloc(size_t nelem, size_t elsize);
00087   void *  ats_realloc(void *ptr, size_t size);
00088   void *  ats_memalign(size_t alignment, size_t size);
00089   void    ats_free(void *ptr);
00090   void *  ats_free_null(void *ptr);
00091   void    ats_memalign_free(void *ptr);
00092   int     ats_mallopt(int param, int value);
00093 
00094   int     ats_msync(caddr_t addr, size_t len, caddr_t end, int flags);
00095   int     ats_madvise(caddr_t addr, size_t len, int flags);
00096   int     ats_mlock(caddr_t addr, size_t len);
00097 
00098   static inline size_t __attribute__((const)) ats_pagesize(void)
00099   {
00100     static size_t page_size;
00101 
00102     if (page_size)
00103       return page_size;
00104 
00105 #if defined(HAVE_SYSCONF) && defined(_SC_PAGESIZE)
00106     page_size = (size_t)sysconf(_SC_PAGESIZE);
00107 #elif defined(HAVE_GETPAGESIZE)
00108     page_size = (size_t)getpagesize()
00109 #else
00110     page_size = (size_t)8192;
00111 #endif
00112 
00113     return page_size;
00114   }
00115 
00116 /* Some convenience wrappers around strdup() functionality */
00117 char *_xstrdup(const char *str, int length, const char *path);
00118 
00119 #define ats_strdup(p)        _xstrdup((p), -1, NULL)
00120 #define ats_strndup(p,n)     _xstrdup((p), n, NULL)
00121 
00122 #ifdef __cplusplus
00123 }
00124 #endif
00125 
00126 #ifdef __cplusplus
00127 
00128 template <typename PtrType, typename SizeType>
00129 static inline IOVec
00130 make_iovec(PtrType ptr, SizeType sz) {
00131   IOVec iov = { ptr, static_cast<size_t>(sz) };
00132   return iov;
00133 }
00134 
00135 template <typename PtrType, unsigned N>
00136 static inline IOVec
00137 make_iovec(PtrType (&array)[N]) {
00138   IOVec iov = { &array[0], static_cast<size_t>(sizeof(array)) };
00139   return iov;
00140 }
00141 
00142 /** Set data to zero.
00143 
00144     Calls @c memset on @a t with a value of zero and a length of @c
00145     sizeof(t). This can be used on ordinary and array variables. While
00146     this can be used on variables of intrinsic type it's inefficient.
00147 
00148     @note Because this uses templates it cannot be used on unnamed or
00149     locally scoped structures / classes. This is an inherent
00150     limitation of templates.
00151 
00152     Examples:
00153     @code
00154     foo bar; // value.
00155     ink_zero(bar); // zero bar.
00156 
00157     foo *bar; // pointer.
00158     ink_zero(bar); // WRONG - makes the pointer @a bar zero.
00159     ink_zero(*bar); // zero what bar points at.
00160 
00161     foo bar[ZOMG]; // Array of structs.
00162     ink_zero(bar); // Zero all structs in array.
00163 
00164     foo *bar[ZOMG]; // array of pointers.
00165     ink_zero(bar); // zero all pointers in the array.
00166     @endcode
00167     
00168  */
00169 template < typename T > inline void
00170 ink_zero(T& t) {
00171   memset(&t, 0, sizeof(t));
00172 }
00173 
00174 /** Scoped resources.
00175 
00176     An instance of this class is used to hold a contingent resource. When this object goes out of scope
00177     the resource is destroyed. If the resource needs to be kept valid it can be released from this container.
00178     The standard usage pattern is
00179     - Allocate resource.
00180     - Perform various other checks or resource allocations which, if they fail, require this resource to be destroyed.
00181     - Release the resource.
00182 
00183     This serves as a base implementation, actual use is usually through specialized subclasses.
00184 
00185     @see ats_scoped_fd
00186     @see ats_scoped_mem
00187     @see ats_scoped_obj
00188 
00189     For example, if you open a file descriptor and have to do other checks which result in having to call
00190     @c close in each @c if clause.
00191 
00192     @code
00193     int fd = open(...);
00194     if (X) { Log(...); close(fd); return -1; }
00195     if (Y) { Log(...); close(fd); return -1; }
00196     ...
00197     return fd;
00198     @endcode
00199 
00200     Change this to
00201     @code
00202     ats_scoped_fd fd(open(...);
00203     if (X) { Log(...) return; } // fd is closed upon return.
00204     if (Y) { Log(...) return; } // fd is closed upon return.
00205     fd.release(); // fd will not be automatically closed after this.
00206     return fd;
00207     @endcode
00208 
00209     The @a TRAITS class must have the following members.
00210 
00211     @code
00212     value_type; // Declaration type of the resource.
00213     RT initValue(); // Return canonical initialization value for RT.
00214     bool isValid(RT); // Check for validity. Can take a reference or const reference.
00215     void destroy(RT); // Cleanup. Can take a reference.
00216     @endcode
00217 
00218     @c isValid should return @c true if the resource instance is valid and @c false if it is not valid.
00219 
00220     @c initValue must be a constant value of @a RT such that @c isValid(INVALID) is @c false. This
00221     is used to initialize the object when the container is empty.
00222 
00223     @c destroy should perform cleanup on the object.
00224 
00225     @internal One might think the initialization value should be a constant but you can't initialize
00226     non-integral class constants (such as pointers) in C++ (you can in C++ eleventy but we can't
00227     require that). We can only hope the compiler is smart enough to optimize out functions returning
00228     constants.
00229 
00230 */
00231 
00232 template <
00233   typename TRAITS ///< Traits object.
00234 >
00235 class ats_scoped_resource
00236 {
00237 public:
00238   typedef TRAITS Traits; ///< Make template arg available.
00239   typedef typename TRAITS::value_type value_type; ///< Import value type.
00240   typedef ats_scoped_resource self; ///< Self reference type.
00241 
00242 public:
00243 
00244   /// Default constructor - an empty container.
00245   ats_scoped_resource() : _r(Traits::initValue()) {}
00246 
00247   /// Construct with contained resource.
00248   explicit ats_scoped_resource(value_type rt) : _r(rt) {}
00249 
00250   /// Destructor.
00251   ~ats_scoped_resource() {
00252     if (Traits::isValid(_r))
00253       Traits::destroy(_r);
00254   }
00255 
00256   /// Automatic conversion to resource type.
00257   operator value_type () const {
00258     return _r;
00259   }
00260   /// Explicit conversion to resource type.
00261   /// @note Syntactic sugar for @c static_cast<value_type>(instance). Required when passing to var arg function
00262   /// as automatic conversion won't be done.
00263   value_type get() const {
00264     return _r;
00265   }
00266 
00267   /** Release resource from this container.
00268       After this call, the resource will @b not cleaned up when this container is destructed.
00269 
00270       @note Although direct assignment is forbidden due to the non-obvious semantics, a pointer can
00271       be moved (@b not copied) from one instance to another using this method.
00272       @code
00273       new_ptr = old_ptr.release();
00274       @endcode
00275       This is by design.
00276 
00277       @return The no longer contained resource.
00278   */
00279   value_type release() {
00280     value_type zret = _r;
00281     _r = Traits::initValue();
00282     return zret;
00283   }
00284 
00285   /** Place a new resource in the container.
00286       Any resource currently contained is destroyed.
00287   */
00288   self& operator = (value_type rt) {
00289     if (Traits::isValid(_r)) Traits::destroy(_r);
00290     _r = rt;
00291     return *this;
00292   }
00293 
00294   bool operator == (value_type rt) const {
00295     return _r == rt;
00296   }
00297 
00298   bool operator != (value_type rt) const {
00299     return _r != rt;
00300   }
00301 
00302 protected:
00303   value_type _r; ///< Resource.
00304 private:
00305   ats_scoped_resource(self const&); ///< Copy constructor not permitted.
00306   self& operator = (self const&); ///< Self assignment not permitted.
00307 
00308 };
00309 
00310 namespace detail {
00311 /** Traits for @c ats_scoped_resource for file descriptors.
00312  */
00313   struct SCOPED_FD_TRAITS
00314   {
00315     typedef int value_type;
00316     static int initValue() { return -1; }
00317     static bool isValid(int fd) { return fd >= 0; }
00318     static void destroy(int fd) { close(fd); }
00319   };
00320 }
00321 /** File descriptor as a scoped resource.
00322 
00323     @internal This needs to be a class and not just a @c typedef because the
00324     pseudo-bool operator is required to avoid ambiguity for non-pointer
00325     resources, but creates ambiguity for pointer resources.
00326  */
00327 class ats_scoped_fd : public ats_scoped_resource<detail::SCOPED_FD_TRAITS>
00328 {
00329 public:
00330   typedef ats_scoped_resource<detail::SCOPED_FD_TRAITS> super; ///< Super type.
00331   typedef ats_scoped_fd self; ///< Self reference type.
00332   typedef bool (self::*pseudo_bool)() const; ///< Bool operator type.
00333 
00334   /// Default constructor (invalid file descriptor).
00335   ats_scoped_fd()
00336   { }
00337   /// Construct with file descriptor.
00338   explicit ats_scoped_fd(value_type v) : super(v)
00339   { }
00340 
00341   /// Assign a file descriptor @a fd.
00342   self& operator = (value_type fd) {
00343     super::operator=(fd);
00344     return *this;
00345   }
00346 
00347   /// Enable direct validity check in an @c if statement w/o ambiguity with @c int conversion.
00348   operator pseudo_bool () const {
00349     return Traits::isValid(_r) ?  &self::operator! : 0;
00350   }
00351 
00352   /// Not valid check.
00353   bool operator ! () const {
00354     return ! Traits::isValid(_r);
00355   }
00356 };
00357 
00358 namespace detail {
00359 /** Traits for @c ats_scoped_resource for pointers from @c ats_malloc.
00360  */
00361   template <
00362     typename T ///< Underlying type (not the pointer type).
00363   >
00364   struct SCOPED_MALLOC_TRAITS
00365   {
00366     typedef T* value_type;
00367     static T*  initValue() { return NULL; }
00368     static bool isValid(T* t) { return 0 != t; }
00369     static void destroy(T* t) { ats_free(t); }
00370   };
00371 
00372   /// Traits for @c ats_scoped_resource for objects using @c new and @c delete.
00373   template <
00374     typename T ///< Underlying type - not the pointer type.
00375   >
00376   struct SCOPED_OBJECT_TRAITS
00377   {
00378     typedef T* value_type;
00379     static T* initValue() { return NULL; }
00380     static bool isValid(T* t) { return 0 != t; }
00381     static void destroy(T* t) { delete t; }
00382   };
00383 }
00384 
00385 /** Specialization of @c ats_scoped_resource for strings.
00386     This contains an allocated string that is cleaned up if not explicitly released.
00387 */
00388 class ats_scoped_str : public ats_scoped_resource<detail::SCOPED_MALLOC_TRAITS<char> >
00389 {
00390  public:
00391   typedef ats_scoped_resource<detail::SCOPED_MALLOC_TRAITS<char> > super; ///< Super type.
00392   typedef ats_scoped_str self; ///< Self reference type.
00393 
00394   /// Default constructor (no string).
00395   ats_scoped_str()
00396   { }
00397   /// Construct and allocate @a n bytes for a string.
00398   explicit ats_scoped_str(size_t n) : super(static_cast<char*>(ats_malloc(n)))
00399   { }
00400   /// Put string @a s in this container for cleanup.
00401   explicit ats_scoped_str(char* s) : super(s)
00402   { }
00403   /// Assign a string @a s to this container.
00404   self& operator = (char* s) {
00405     super::operator=(s);
00406     return *this;
00407   }
00408 };
00409 
00410 /** Specialization of @c ats_scoped_resource for pointers allocated with @c ats_malloc.
00411  */
00412 template <
00413   typename T ///< Underlying (not pointer) type.
00414 >
00415 class ats_scoped_mem : public ats_scoped_resource<detail::SCOPED_MALLOC_TRAITS<T> >
00416 {
00417 public:
00418   typedef ats_scoped_resource<detail::SCOPED_MALLOC_TRAITS<T> > super; ///< Super type.
00419   typedef ats_scoped_mem self; ///< Self reference.
00420 
00421   self& operator = (T* ptr) {
00422     super::operator=(ptr);
00423     return *this;
00424   }
00425 };
00426 
00427 /** Specialization of @c ats_scoped_resource for objects.
00428     This handles a pointer to an object created by @c new and destroyed by @c delete.
00429 */
00430 
00431 template <
00432   typename T /// Underlying (not pointer) type.
00433 >
00434 class ats_scoped_obj : public ats_scoped_resource<detail::SCOPED_OBJECT_TRAITS<T> >
00435 {
00436 public:
00437   typedef ats_scoped_resource<detail::SCOPED_OBJECT_TRAITS<T> > super; ///< Super type.
00438   typedef ats_scoped_obj self; ///< Self reference.
00439 
00440   self& operator = (T* obj) {
00441     super::operator=(obj);
00442     return *this;
00443   }
00444 };
00445 
00446 /** Combine two strings as file paths.
00447      Trailing and leading separators for @a lhs and @a rhs respectively
00448      are handled to yield exactly one separator.
00449      @return A newly @x ats_malloc string of the combined paths.
00450 */
00451 inline char*
00452 path_join (ats_scoped_str const& lhs, ats_scoped_str  const& rhs)
00453 {
00454   size_t ln = strlen(lhs);
00455   size_t rn = strlen(rhs);
00456   char const* rptr = rhs; // May need to be modified.
00457 
00458   if (ln && lhs[ln-1] == '/') --ln; // drop trailing separator.
00459   if (rn && *rptr == '/') --rn, ++rptr; // drop leading separator.
00460 
00461   ats_scoped_str x(ln + rn + 2);
00462 
00463   memcpy(x, lhs, ln);
00464   x[ln] = '/';
00465   memcpy(x + ln + 1,  rptr, rn);
00466   x[ln+rn+1] = 0; // terminate string.
00467 
00468   return x.release();
00469 }
00470 #endif  /* __cplusplus */
00471 
00472 #endif

Generated by  doxygen 1.7.1