// Module: Log4CPLUS // File: threads.cxx // Created: 6/2001 // Author: Tad E. Smith // // // Copyright 2001-2017 Tad E. Smith // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include #include #include #include #ifdef LOG4CPLUS_HAVE_SYS_TYPES_H #include #endif #ifdef LOG4CPLUS_HAVE_SYS_SYSCALL_H #include #endif #ifdef LOG4CPLUS_HAVE_ERRNO_H #include #endif #ifdef LOG4CPLUS_HAVE_UNISTD_H #include #endif #if defined(LOG4CPLUS_USE_PTHREADS) # include # include # include #elif defined (LOG4CPLUS_USE_WIN32_THREADS) # include #endif #include #include #include #include #include #ifndef LOG4CPLUS_SINGLE_THREADED #include #include #include #include #include #include #include #include #endif // LOG4CPLUS_SINGLE_THREADED namespace log4cplus { namespace thread { LOG4CPLUS_EXPORT void blockAllSignals() { #if defined (LOG4CPLUS_USE_PTHREADS) // Block all signals. sigset_t signal_set; sigfillset (&signal_set); pthread_sigmask (SIG_BLOCK, &signal_set, nullptr); #endif } LOG4CPLUS_EXPORT void yield() { #if defined(LOG4CPLUS_USE_PTHREADS) sched_yield(); #elif defined(_WIN32) if (! SwitchToThread ()) Sleep (0); #endif } #if defined(LOG4CPLUS_SINGLE_THREADED) static log4cplus::tstring thread_name LOG4CPLUS_INIT_PRIORITY (LOG4CPLUS_INIT_PRIORITY_BASE - 1) (LOG4CPLUS_TEXT("single")); static log4cplus::tstring thread_name2 LOG4CPLUS_INIT_PRIORITY (LOG4CPLUS_INIT_PRIORITY_BASE - 1) (thread_name); #endif LOG4CPLUS_EXPORT log4cplus::tstring const & getCurrentThreadName() { #if ! defined (LOG4CPLUS_SINGLE_THREADED) log4cplus::tstring & name = log4cplus::internal::get_thread_name_str (); if (LOG4CPLUS_UNLIKELY (name.empty ())) { log4cplus::tostringstream tmp; tmp << impl::getCurrentThreadId (); name = tmp.str (); } #else log4cplus::tstring & name = thread_name; if (LOG4CPLUS_UNLIKELY(name.empty())) { name = LOG4CPLUS_TEXT("single"); } #endif return name; } namespace { static bool get_current_thread_name_alt (log4cplus::tostream * s) { log4cplus::tostream & os = *s; #if defined (LOG4CPLUS_USE_PTHREADS) && defined (__linux__) \ && defined (LOG4CPLUS_HAVE_GETTID) pid_t tid = syscall (SYS_gettid); os << tid; #elif defined (__CYGWIN__) unsigned long tid = cygwin::get_current_win32_thread_id (); os << tid; #else os << getCurrentThreadName (); #endif return true; } } // namespace LOG4CPLUS_EXPORT log4cplus::tstring const & getCurrentThreadName2() { #if ! defined (LOG4CPLUS_SINGLE_THREADED) log4cplus::tstring & name = log4cplus::internal::get_thread_name2_str (); if (LOG4CPLUS_UNLIKELY (name.empty ())) { log4cplus::tostringstream tmp; get_current_thread_name_alt (&tmp); name = tmp.str (); } #else log4cplus::tstring & name = thread_name2; if (LOG4CPLUS_UNLIKELY(name.empty())) { name = getCurrentThreadName(); } #endif return name; } LOG4CPLUS_EXPORT void setCurrentThreadName(const log4cplus::tstring & name) { #if ! defined (LOG4CPLUS_SINGLE_THREADED) log4cplus::internal::get_thread_name_str() = name; #else thread_name = name; #endif } LOG4CPLUS_EXPORT void setCurrentThreadName2(const log4cplus::tstring & name) { #if ! defined (LOG4CPLUS_SINGLE_THREADED) log4cplus::internal::get_thread_name2_str() = name; #else thread_name2 = name; #endif } #ifndef LOG4CPLUS_SINGLE_THREADED // // // AbstractThread::AbstractThread () : flags (0) { } bool AbstractThread::isRunning() const { return (flags & fRUNNING) != 0; } void AbstractThread::start() { try { flags |= fRUNNING; thread.reset ( new std::thread ([this] (AbstractThreadPtr const & thread_ptr) { (void) thread_ptr; blockAllSignals (); helpers::LogLog & loglog = helpers::getLogLog(); try { this->run (); } catch (std::exception const & e) { tstring err (LOG4CPLUS_TEXT ("threadStartFunc()") LOG4CPLUS_TEXT ("- run() terminated with an exception: ")); err += LOG4CPLUS_C_STR_TO_TSTRING(e.what()); loglog.warn(err); } catch(...) { loglog.warn(LOG4CPLUS_TEXT("threadStartFunc()") LOG4CPLUS_TEXT ("- run() terminated with an exception.")); } this->flags &= ~fRUNNING; threadCleanup (); }, AbstractThreadPtr (this))); } catch (...) { flags &= ~fRUNNING; throw; } } void AbstractThread::join () const { if (! thread || (flags & fJOINED) == fJOINED) throw std::logic_error ("this thread is not running"); thread->join (); flags |= +fJOINED; } AbstractThread::~AbstractThread() { if ((flags & fJOINED) == 0) thread->detach (); } #endif // LOG4CPLUS_SINGLE_THREADED } } // namespace log4cplus { namespace thread {