// -*- indent-tabs-mode: nil -*- #ifndef __ARC_UTILS_H__ #define __ARC_UTILS_H__ #include // NOTE: On Solaris errno is not working properly if cerrno is included first #include #include #include namespace Arc { /** \addtogroup common * @{ */ /// Portable function for getting environment variables. Protected by shared lock. std::string GetEnv(const std::string& var); /// Portable function for getting environment variables. Protected by shared lock. std::string GetEnv(const std::string& var, bool &found); /// Portable function for getting all environment variables. Protected by shared lock. std::list GetEnv(); /// Portable function for setting environment variables. Protected by exclusive lock. bool SetEnv(const std::string& var, const std::string& value, bool overwrite = true); /// Portable function for unsetting environment variables. Protected by exclusive lock. void UnsetEnv(const std::string& var); // These are functions to be used used exclusively for solving // problem with specific libraries which depend too much on // environment variables. /// Obtain lock on environment. /** For use with external libraries using unprotected setenv/getenv in a multi-threaded environment. */ void EnvLockAcquire(void); /// Release lock on environment. /** For use with external libraries using unprotected setenv/getenv in a multi-threaded environment. */ void EnvLockRelease(void); /// Start code which is using setenv/getenv. /** For use with external libraries using unprotected setenv/getenv in a multi-threaded environment. Must always have corresponding EnvLockUnwrap. * \param all set to true for setenv and false for getenv. */ void EnvLockWrap(bool all = false); /// End code which is using setenv/getenv. /** For use with external libraries using unprotected setenv/getenv in a multi-threaded environment. \param all must be same as in corresponding EnvLockWrap. */ void EnvLockUnwrap(bool all = false); /// Use after fork() to reset all internal variables and release all locks. /** For use with external libraries using unprotected setenv/getenv in a multi-threaded environment. This function is deprecated. */ void EnvLockUnwrapComplete(void); /// Class to provide automatic locking/unlocking of environment on creation/destruction. /** For use with external libraries using unprotected setenv/getenv in a multi-threaded environment. \headerfile Utils.h arc/Utils.h */ class EnvLockWrapper { private: bool all_; public: /// Create a new environment lock for using setenv/getenv. /** \param all set to true for setenv and false for getenv. */ EnvLockWrapper(bool all = false):all_(all) { EnvLockWrap(all_); }; /// Release environment lock. ~EnvLockWrapper(void) { EnvLockUnwrap(all_); }; }; /// Marks off a section of code which should not be interrupted by signals. /** \headerfile Utils.h arc/Utils.h */ class InterruptGuard { public: InterruptGuard(); ~InterruptGuard(); private: void (*saved_sigint_handler)(int); }; /// Portable function for obtaining description of last system error std::string StrError(int errnum = errno); /// Wrapper for pointer with automatic destruction /** If ordinary pointer is wrapped in instance of this class it will be automatically destroyed when instance is destroyed. This is useful for maintaining pointers in scope of one function. Only pointers returned by new() are supported. \headerfile Utils.h arc/Utils.h */ template class AutoPointer { private: T *object; void (*deleter)(T*); static void DefaultDeleter(T* o) { delete o; } void operator=(const AutoPointer&); #if __cplusplus >= 201103L private: AutoPointer(AutoPointer const&); #else // Workaround for older gcc which does not implement construction // of new elements in std::list according to specification. public: AutoPointer(AutoPointer const& o) : object(NULL), deleter(&DefaultDeleter) { operator=(const_cast&>(o)); } #endif public: /// NULL pointer constructor AutoPointer(void (*d)(T*) = &DefaultDeleter) : object(NULL), deleter(d) {} /// Constructor which wraps pointer and optionally defines deletion function AutoPointer(T *o, void (*d)(T*) = &DefaultDeleter) : object(o), deleter(d) {} /// Moving constructor AutoPointer(AutoPointer& o) : object(o.Release()), deleter(o.deleter) {} /// Destructor destroys wrapped object using assigned deleter ~AutoPointer(void) { if (object) if(deleter) (*deleter)(object); object = NULL; } AutoPointer& operator=(T* o) { if (object) if(deleter) (*deleter)(object); object = o; return *this; } AutoPointer& operator=(AutoPointer& o) { if (object) if(deleter) (*deleter)(object); object = o.object; o.object = NULL; return *this; } /// For referring wrapped object T& operator*(void) const { return *object; } /// For referring wrapped object T* operator->(void) const { return object; } /// Returns false if pointer is NULL and true otherwise. operator bool(void) const { return (object != NULL); } /// Returns true if pointer is NULL and false otherwise. bool operator!(void) const { return (object == NULL); } /// Cast to original pointer T* Ptr(void) const { return object; } T& operator[](int pos) { return object[pos]; } T const& operator[](int pos) const { return object[pos]; } /// Release referred object so that it can be passed to other container T* Release(void) { T* tmp = object; object = NULL; return tmp; } // Convenience method to pass as argument to function which allocates object. T** ForAssign() { if (object) if(deleter) (*deleter)(object); object = NULL; return &object; } }; /// Wrapper for pointer with automatic destruction and multiple references /** If ordinary pointer is wrapped in instance of this class it will be automatically destroyed when all instances referring to it are destroyed. This is useful for maintaining pointers referred from multiple structures with automatic destruction of original object when last reference is destroyed. It is similar to Java approach with a difference that destruction time is strictly defined. Only pointers returned by new() are supported. This class is not thread-safe. \headerfile Utils.h arc/Utils.h */ template class CountedPointer { private: template class Base { private: Base(Base

&); public: int cnt; P *ptr; bool released; Base(P *p) : cnt(0), ptr(p), released(false) { add(); } ~Base(void) { if (ptr && !released) delete ptr; } Base

* add(void) { ++cnt; return this; } bool rem(void) { if (--cnt == 0) { if(!released) delete this; return true; } return false; } }; Base *object; public: CountedPointer(T *p = NULL) : object(new Base(p)) {} CountedPointer(const CountedPointer& p) : object(p.object->add()) {} ~CountedPointer(void) { object->rem(); } CountedPointer& operator=(T *p) { if (p != object->ptr) { object->rem(); object = new Base(p); } return *this; } CountedPointer& operator=(const CountedPointer& p) { if (p.object->ptr != object->ptr) { object->rem(); object = p.object->add(); } return *this; } /// For referring wrapped object T& operator*(void) const { return *(object->ptr); } /// For referring wrapped object T* operator->(void) const { return (object->ptr); } /// Returns false if pointer is NULL and true otherwise. operator bool(void) const { return ((object->ptr) != NULL); } /// Returns true if pointer is NULL and false otherwise. bool operator!(void) const { return ((object->ptr) == NULL); } /// Returns true if pointers are equal bool operator==(const CountedPointer& p) const { return ((object->ptr) == (p.object->ptr)); } /// Returns true if pointers are not equal bool operator!=(const CountedPointer& p) const { return ((object->ptr) != (p.object->ptr)); } /// Comparison operator bool operator<(const CountedPointer& p) const { return ((object->ptr) < (p.object->ptr)); } /// Cast to original pointer T* Ptr(void) const { return (object->ptr); } /// Release referred object so that it can be passed to other container T* Release(void) { T* tmp = object->ptr; object->released = true; return tmp; } }; /// Load library and keep persistent. bool PersistentLibraryInit(const std::string& name); /** @{ */ } // namespace Arc #endif // __ARC_UTILS_H__