Example #1
0
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_;
}
Example #2
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_ };
 }
Example #3
0
 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;
 }
Example #4
0
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();
}
Example #5
0
//! 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);
    }
}
Example #6
0
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
            }
        }
    }
}
Example #7
0
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");
    }
}
Example #9
0
static bool Hook_Want_Disable()
{
    if (BOOST_UNLIKELY(!config.lockstep || !enabled || disabling_plugin || unloading_plugin))
    {
        lockstep_want_shutdown = true;
    }
    return lockstep_want_shutdown;
}
Example #10
0
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;
}
Example #11
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;
 }
Example #13
0
//! 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;
 }
Example #16
0
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);
}
Example #17
0
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);
}
Example #18
0
//! 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_) };
 }
Example #21
0
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");
    }
}
Example #22
0
//! 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"));
        }
    }
}
Example #23
0
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");
    }
Example #24
0
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");
    }
}
Example #25
0
//! 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"));
        }
    }
}
Example #26
0
//! 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"));
        }
    }
}
Example #27
0
//! 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;
}
Example #28
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;
}
Example #29
0
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);
        }
    }
}
Example #30
0
//! 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);
}