bool interprocess_condition_variable::wait(interprocess_mutex::optional_unlock& lock, boost::detail::winapi::HANDLE_ abort_handle) { int32_t waiters = m_shared_state->m_waiters; if (waiters < 0) { // We need to select a new semaphore to block on m_current_semaphore = get_unused_semaphore(); ++m_shared_state->m_generation; m_shared_state->m_semaphore_id = m_current_semaphore->m_id; waiters = 0; } else { // Avoid integer overflow if (BOOST_UNLIKELY(waiters >= ((std::numeric_limits< int32_t >::max)() - 1))) BOOST_LOG_THROW_DESCR(limitation_error, "Too many waiters on an interprocess condition variable"); // Make sure we use the right semaphore to block on const uint32_t id = m_shared_state->m_semaphore_id; if (m_current_semaphore->m_id != id) m_current_semaphore = get_semaphore(id); } m_shared_state->m_waiters = waiters + 1; const uint32_t generation = m_shared_state->m_generation; boost::detail::winapi::HANDLE_ handles[2u] = { m_current_semaphore->m_semaphore.get_handle(), abort_handle }; interprocess_mutex* const mutex = lock.disengage(); mutex->unlock(); boost::detail::winapi::DWORD_ retval = boost::detail::winapi::WaitForMultipleObjects(2u, handles, false, boost::detail::winapi::INFINITE_); if (BOOST_UNLIKELY(retval == boost::detail::winapi::WAIT_FAILED_)) { const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError(); // Although highly unrealistic, it is possible that it took so long for the current thread to enter WaitForMultipleObjects that // another thread has managed to destroy the semaphore. This can happen if the semaphore remains in a non-zero state // for too long, which means that another process died while being blocked on the semaphore, and the semaphore was signalled, // and the non-zero state timeout has passed. In this case the most logical behavior for the wait function is to return as // if because of a wakeup. if (err == ERROR_INVALID_HANDLE) retval = boost::detail::winapi::WAIT_OBJECT_0_; else BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, "Failed to block on an interprocess semaphore object", (err)); } // Have to unconditionally lock the mutex here mutex->lock(); lock.engage(*mutex); if (generation == m_shared_state->m_generation && m_shared_state->m_waiters > 0) --m_shared_state->m_waiters; return retval == boost::detail::winapi::WAIT_OBJECT_0_; }
future< R > get_future() { if ( BOOST_UNLIKELY( obtained_) ) { throw future_already_retrieved{}; } if ( BOOST_UNLIKELY( ! future_) ) { throw promise_uninitialized{}; } obtained_ = true; return future< R >{ future_ }; }
char const* parse_token_to_eol( char const* p, char const* last, char const*& token_last, error_code& ec) { for(;; ++p) { if(p >= last) { ec = error::need_more; return p; } if(BOOST_UNLIKELY(! is_print(*p))) if((BOOST_LIKELY(static_cast< unsigned char>(*p) < '\040') && BOOST_LIKELY(*p != '\011')) || BOOST_UNLIKELY(*p == '\177')) goto found_control; } found_control: if(BOOST_LIKELY(*p == '\r')) { if(++p >= last) { ec = error::need_more; return last; } if(*p++ != '\n') { ec = error::bad_line_ending; return last; } token_last = p - 2; } #if 0 // VFALCO This allows `\n` by itself // to terminate a line else if(*p == '\n') { token_last = p; ++p; } #endif else { // invalid character return nullptr; } return p; }
void RestDispatcher::sink(HTTP::Connection* conn) { HTTP::setShouldConnectionBeClosed(conn->request(), conn->response()); if (BOOST_UNLIKELY(table_.empty())) { throw std::logic_error("Dispatch table is empty"); } const auto& path = conn->request().uri; auto it = std::lower_bound(table_.begin(), table_.end(), path, Comparator()); for (auto end = table_.end(); it != end && it->first == path; ++it) { if (it->second.handle(conn)) { return; // Properly handled } } conn->response() .setCode(HTTP::HttpCode::NotFound) .setBody("Unroutable request"); conn->sendResponse(); }
//! Waits for the object to become signalled BOOST_LOG_API void futex_based_event::wait() { if (m_state.exchange(0, boost::memory_order_acq_rel) == 0) { while (true) { if (::syscall(BOOST_LOG_SYS_FUTEX, &m_state.storage(), BOOST_LOG_FUTEX_WAIT, 0, NULL, NULL, 0) == 0) { // Another thread has set the event while sleeping break; } const int err = errno; if (err == EWOULDBLOCK) { // Another thread has set the event before sleeping break; } else if (BOOST_UNLIKELY(err != EINTR)) { BOOST_THROW_EXCEPTION(system::system_error( err, system::system_category(), "Failed to block on the futex")); } } m_state.store(0, boost::memory_order_relaxed); } }
void recursive_timed_mutex::unlock() { context * active_ctx = context::active(); detail::spinlock_lock lk{ wait_queue_splk_ }; if ( BOOST_UNLIKELY( active_ctx != owner_) ) { throw lock_error{ std::make_error_code( std::errc::operation_not_permitted), "boost fiber: no privilege to perform the operation" }; } if ( 0 == --count_) { owner_ = nullptr; if ( ! wait_queue_.empty() ) { context * ctx = & wait_queue_.front(); wait_queue_.pop_front(); std::intptr_t expected = reinterpret_cast< std::intptr_t >( this); if ( ctx->twstatus.compare_exchange_strong( expected, static_cast< std::intptr_t >( -1), std::memory_order_acq_rel) ) { // notify before timeout intrusive_ptr_release( ctx); // notify context active_ctx->schedule( ctx); } else if ( static_cast< std::intptr_t >( 0) == expected) { // no timed-wait op. // notify context active_ctx->schedule( ctx); } else { // timed-wait op. // expected == -1: notify after timeout, same timed-wait op. // expected == <any>: notify after timeout, another timed-wait op. was already started intrusive_ptr_release( ctx); // re-schedule next } } } }
BOOST_NOINLINE std::ostream & dfai_debug_log() { static std::ofstream log; if (BOOST_UNLIKELY(!log.is_open())) { log.open("df-ai-debug.log", std::ios::out | std::ios::app); log << "\n\ndf-ai debug log opened. version information follows:" << std::endl; ai_version(log); color_ostream_proxy out(Core::getInstance().getConsole()); out << std::endl; out << std::endl; out << COLOR_LIGHTRED << "It was inevitable. "; out << COLOR_YELLOW << "df-ai has encountered an issue." << std::endl; out << "Some information that might help fix this has been written to a file named "; out << COLOR_LIGHTCYAN << "df-ai-debug.log"; out << COLOR_YELLOW << " in your Dwarf Fortress folder." << std::endl; out << "If you would like to help, create an issue at https://github.com/BenLubar/df-ai/issues/new (you can drag or copy and paste the log file into the editor)." << std::endl; #ifndef DFAI_RELEASE out << COLOR_LIGHTRED << "If your game crashes after this message, please attach a debugger or use a release mode version of df-ai." << std::endl; #endif out << std::endl; out << std::endl; } return log; }
thread_specific_base::thread_specific_base() { m_Key = TlsAlloc(); if (BOOST_UNLIKELY(m_Key == TLS_OUT_OF_INDEXES)) { BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted"); } }
static bool Hook_Want_Disable() { if (BOOST_UNLIKELY(!config.lockstep || !enabled || disabling_plugin || unloading_plugin)) { lockstep_want_shutdown = true; } return lockstep_want_shutdown; }
static bool lockstep_mainloop() { //NO INTERFACE LEFT, QUIT if (BOOST_UNLIKELY(gview->view.child == 0)) { return true; } //GRAB CURRENT SCREEN AT THE END OF THE LIST df::viewscreen *currentscreen = Gui::getCurViewscreen(false); //MOVE SCREENS BACK switch (currentscreen->breakdown_level) { case interface_breakdown_types::NONE: { currentscreen->logic(); if (currentscreen->movies_okay()) { //HANDLE MOVIES lockstep_handlemovie(false); } // df-ai: don't process input break; } case interface_breakdown_types::QUIT: { lockstep_handlemovie(true); return true; } case interface_breakdown_types::STOPSCREEN: { if (currentscreen->movies_okay()) { //HANDLE MOVIES lockstep_handlemovie(false); } lockstep_removescreen(currentscreen); break; } case interface_breakdown_types::TOFIRST: { if (currentscreen->movies_okay()) { //HANDLE MOVIES lockstep_handlemovie(false); } lockstep_remove_to_first(); break; } } return 0; }
bool GusdUSD_XformCache::GetLocalToWorldTransform(const UsdPrim& prim, UsdTimeCode time, UT_Matrix4D& xform) { const auto info = GetXformInfo(prim); if(BOOST_UNLIKELY(!info)) return false; // See if we can remap the time to for unvarying xforms. if(!time.IsDefault() && !info->WorldXformIsMaybeTimeVarying()) { /* XXX: we know we're not time varying, but that doesn't mean that we can key default, since there might still be a single varying value that we'd miss. Key off of time=0 instead.*/ time = UsdTimeCode(0.0); } _VaryingKey key(GusdUSD_VaryingPropertyKey(prim, time)); if(auto item = _worldXforms.findItem(key)) { xform = UTverify_cast<const _CappedXformItem*>(item.get())->xform; return true; } /* XXX: Race is possible when setting computed value, but it's preferable to have multiple threads compute the same thing than to cause lock contention.*/ if(_GetLocalTransformation(prim, time, xform, info)) { if(BOOST_UNLIKELY(!info->HasParentXform())) { _worldXforms.addItem(key, UT_CappedItemHandle( new _CappedXformItem(xform))); return true; } UsdPrim parent = prim.GetParent(); UT_ASSERT_P(parent); UT_Matrix4D parentXf; if(GetLocalToWorldTransform(parent, time, parentXf)) { xform *= parentXf; _worldXforms.addItem( key, UT_CappedItemHandle(new _CappedXformItem(xform))); return true; } } return false; }
void reset() { if ( BOOST_UNLIKELY( ! valid() ) ) { throw packaged_task_uninitialized{}; } packaged_task tmp; tmp.task_ = task_; task_ = tmp.task_->reset(); obtained_ = false; }
//! Default constructor BOOST_LOG_API sem_based_event::sem_based_event() : m_state() { if (BOOST_UNLIKELY(sem_init(&m_semaphore, 0, 0) != 0)) { const int err = errno; BOOST_THROW_EXCEPTION(system::system_error( err, system::system_category(), "Failed to initialize semaphore")); } }
static void allocate(void*& stg) { pthread_key_type key = NULL; const int res = pthread_key_create(&key, NULL); if (BOOST_UNLIKELY(res != 0)) { BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted"); } stg = static_cast< void* >(key); }
static void allocate(void*& stg) { pthread_key_caster caster = {}; const int res = pthread_key_create(&caster.as_key, NULL); if (BOOST_UNLIKELY(res != 0)) { BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted"); } stg = caster.as_storage; }
bool GusdUSD_XformCache::GetLocalTransformation(const UsdPrim& prim, UsdTimeCode time, UT_Matrix4D& xform) { const auto info = GetXformInfo(prim); if(BOOST_UNLIKELY(!info)) return false; return _GetLocalTransformation(prim, time, xform, info); }
void interprocess_semaphore::open(const wchar_t* name) { boost::detail::winapi::HANDLE_ h = boost::detail::winapi::OpenSemaphoreW(boost::detail::winapi::SYNCHRONIZE_ | boost::detail::winapi::SEMAPHORE_MODIFY_STATE_ | boost::detail::winapi::SEMAPHORE_QUERY_STATE_, false, name); if (BOOST_UNLIKELY(h == NULL)) { const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError(); BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, "Failed to open an interprocess semaphore object", (err)); } m_sem.init(h); }
//! Default constructor BOOST_LOG_API winapi_based_event::winapi_based_event() : m_state(0), m_event(CreateEventA(NULL, false, false, NULL)) { if (BOOST_UNLIKELY(!m_event)) { const DWORD err = GetLastError(); BOOST_THROW_EXCEPTION(system::system_error( err, system::system_category(), "Failed to create Windows event")); } }
static void allocate(void*& stg) { pthread_key_type* pkey = new pthread_key_type(); const int res = pthread_key_create(pkey, NULL); if (BOOST_UNLIKELY(res != 0)) { delete pkey; BOOST_LOG_THROW_DESCR(system_error, "TLS capacity depleted"); } stg = pkey; }
future< R > get_future() { if ( obtained_) { throw future_already_retrieved{}; } if ( BOOST_UNLIKELY( ! valid() ) ) { throw packaged_task_uninitialized{}; } obtained_ = true; return future< R >{ boost::static_pointer_cast< detail::shared_state< R > >( task_) }; }
BOOST_FIBERS_DECL void pin_thread( std::uint32_t cpuid) { if ( BOOST_UNLIKELY( -1 == ::processor_bind( P_LWPID, P_MYID, static_cast< processorid_t >( cpuid), 0) ) ) { throw std::system_error( std::error_code( errno, std::system_category() ), "processor_bind() failed"); } }
//! Sets the object to a signalled state BOOST_LOG_API void sem_based_event::set_signalled() { if (!m_state.test_and_set(boost::memory_order_release)) { if (BOOST_UNLIKELY(sem_post(&m_semaphore) != 0)) { const int err = errno; BOOST_THROW_EXCEPTION(system::system_error( err, system::system_category(), "Failed to wake the blocked thread")); } } }
BOOST_FIBERS_DECL void pin_thread( std::uint32_t cpuid) { pthread_spu_t spu; int err = ::pthread_processor_bind_np( PTHREAD_BIND_FORCED_NP, & spu, static_cast< pthread_spu_t >( cpuid), PTHREAD_SELFTID_NP); if ( BOOST_UNLIKELY( 0 != err) ) throw std::system_error( std::error_code( err, std::system_category() ), "pthread_processor_bind_np() failed"); }
BOOST_FIBERS_DECL void pin_thread( std::uint32_t cpuid) { cpu_set_t set; CPU_ZERO( & set); CPU_SET( cpuid, & set); int err = 0; if ( BOOST_UNLIKELY( 0 != ( err = ::pthread_setaffinity_np( ::pthread_self(), sizeof( set), & set) ) ) ) { throw std::system_error( std::error_code( err, std::system_category() ), "pthread_setaffinity_np() failed"); } }
//! Sets the object to a signalled state BOOST_LOG_API void futex_based_event::set_signalled() { if (m_state.exchange(1, boost::memory_order_release) == 0) { if (BOOST_UNLIKELY(::syscall(BOOST_LOG_SYS_FUTEX, &m_state.storage(), BOOST_LOG_FUTEX_WAKE, 1, NULL, NULL, 0) < 0)) { const int err = errno; BOOST_THROW_EXCEPTION(system::system_error( err, system::system_category(), "Failed to wake threads blocked on the futex")); } } }
//! Sets the object to a signalled state BOOST_LOG_API void winapi_based_event::set_signalled() { if (BOOST_INTERLOCKED_COMPARE_EXCHANGE(reinterpret_cast< long* >(&m_state), 1, 0) == 0) { if (BOOST_UNLIKELY(SetEvent(m_event) == 0)) { const DWORD err = GetLastError(); const_cast< volatile boost::uint32_t& >(m_state) = 0; BOOST_THROW_EXCEPTION(system::system_error( err, system::system_category(), "Failed to wake the blocked thread")); } } }
//! Waits for the object to become signalled BOOST_LOG_API void winapi_based_event::wait() { // On Windows we assume that memory view is always actual (Intel x86 and x86_64 arch) if (const_cast< volatile boost::uint32_t& >(m_state) == 0) { if (BOOST_UNLIKELY(WaitForSingleObject(m_event, INFINITE) != 0)) { const DWORD err = GetLastError(); BOOST_THROW_EXCEPTION(system::system_error( err, system::system_category(), "Failed to block on Windows event")); } } const_cast< volatile boost::uint32_t& >(m_state) = 0; }
bool interprocess_semaphore::is_semaphore_zero_count_emulated(boost::detail::winapi::HANDLE_ h) { const boost::detail::winapi::DWORD_ retval = boost::detail::winapi::WaitForSingleObject(h, 0u); if (retval == boost::detail::winapi::wait_timeout) { return true; } else if (BOOST_UNLIKELY(retval != boost::detail::winapi::wait_object_0)) { const boost::detail::winapi::DWORD_ err = boost::detail::winapi::GetLastError(); BOOST_LOG_THROW_DESCR_PARAMS(boost::log::system_error, "Failed to test an interprocess semaphore object for zero count", (err)); } // Restore the decremented counter BOOST_VERIFY(!!boost::detail::winapi::ReleaseSemaphore(h, 1, NULL)); return false; }
void recursive_mutex::unlock() { context * active_ctx = context::active(); detail::spinlock_lock lk( wait_queue_splk_); if ( BOOST_UNLIKELY( active_ctx != owner_) ) { throw lock_error( std::make_error_code( std::errc::operation_not_permitted), "boost fiber: no privilege to perform the operation"); } if ( 0 == --count_) { owner_ = nullptr; if ( ! wait_queue_.empty() ) { context * ctx = & wait_queue_.front(); wait_queue_.pop_front(); active_ctx->schedule( ctx); } } }
//! Waits for the object to become signalled BOOST_LOG_API void sem_based_event::wait() { boost::atomic_thread_fence(boost::memory_order_acq_rel); while (true) { if (sem_wait(&m_semaphore) != 0) { const int err = errno; if (BOOST_UNLIKELY(err != EINTR)) { BOOST_THROW_EXCEPTION(system::system_error( err, system::system_category(), "Failed to block on the semaphore")); } } else break; } m_state.clear(boost::memory_order_relaxed); }