/* vim:set ts=4 sw=4 sts=4 et cindent: */ /* * nanodc - The ncurses DC++ client * Copyright © 2005-2006 Markus Lindqvist * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * Contributor(s): * */ #ifndef _MUTEX_H_ #define _MUTEX_H_ #include #include #include #include #define DEBUG_MUTEX 1 #if DEBUG_MUTEX /** gettid() system call number */ const unsigned int SYS_gettid = 224; /** Returns thread id of the calling thread. * * Implemented only if \c __i386__ is defined. */ inline static pid_t __gettid() { pid_t tid = 0; #ifdef __i386__ __asm__("int $0x80" : "=a" (tid) : "0" (SYS_gettid)); #endif return tid; } template std::string __to_string(T s) { std::ostringstream oss; oss << s; return oss.str(); } #endif // DEBUG_MUTEX namespace utils { /** A wrapper for pthread_mutex_t */ class Mutex { public: /** Initializes the mutex. */ Mutex() { #if DEBUG_MUTEX m_tid = 0; #endif pthread_mutex_init(&m_lock, 0); } /** Locks the mutex. */ void lock() { #if DEBUG_MUTEX if(m_tid != 0 && m_tid == __gettid()) { std::string message = ("Mutex already locked by the same thread: " + __to_string(m_tid)); if(cow::StackTrace::is_enabled()) { std::ostringstream oss; cow::StackTrace trace; trace.generate_frames(); std::copy(trace.begin(), trace.end(), std::ostream_iterator(oss, "\n")); message += "\n" + oss.str(); } else { message += ("\nStack not available"); } message = "echo '" + message + "' >> MUTEX_ERRORS"; system(message.c_str()); return; } m_tid = __gettid(); #endif pthread_mutex_lock(&m_lock); } /** Releases the mutex. */ void unlock() { pthread_mutex_unlock(&m_lock); #if DEBUG_MUTEX m_tid = 0; #endif } /** Get the internal pthread mutex handle. */ pthread_mutex_t *get_mutex() { return &m_lock; } /** Deletes the mutex. */ ~Mutex() { pthread_mutex_destroy(&m_lock); } private: pthread_mutex_t m_lock; #if DEBUG_MUTEX int m_tid; #endif }; } // namespace utils #endif // _MUTEX_H_