Changeset 2fe64ba


Ignore:
Timestamp:
Jul 6, 2023, 4:51:42 PM (10 months ago)
Author:
caparsons <caparson@…>
Branches:
master
Children:
bef2245
Parents:
b4d2b3b
Message:

added support for non-local exceptions

Location:
libcfa/src/concurrency
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/coroutine.cfa

    rb4d2b3b r2fe64ba  
    121121        last = 0p;
    122122        cancellation = 0p;
     123    ehm_state.ehm_buffer{};
     124    ehm_state.buffer_lock{};
     125    ehm_state.ehm_enabled = false;
    123126}
    124127
     
    283286}
    284287
     288
     289////////////////////////////////////////////////////////////////////////////////////////////////////
     290// non local ehm routines
     291
     292// helper for popping from coroutine's ehm buffer
     293inline nonlocal_exception * pop_ehm_head( coroutine$ * this ) {
     294    lock( this->ehm_state.buffer_lock __cfaabi_dbg_ctx2 );
     295    nonlocal_exception * nl_ex = pop_head( this->ehm_state.ehm_buffer );
     296    unlock( this->ehm_state.buffer_lock );
     297    return nl_ex;
     298}
     299
     300// user facing ehm operations
     301forall(T & | is_coroutine(T)) {
     302    // enable/disable non-local exceptions
     303    void enable_ehm( T & cor ) libcfa_public { get_coroutine( cor )->ehm_state.ehm_enabled = true; }
     304    void disable_ehm( T & cor ) libcfa_public { get_coroutine( cor )->ehm_state.ehm_enabled = false; }
     305
     306    // poll for non-local exceptions
     307    bool poll( T & cor ) libcfa_public {
     308        coroutine$ * base_cor = get_coroutine( cor );
     309        nonlocal_exception * nl_ex = pop_ehm_head( base_cor );
     310
     311        // if no exceptions return false
     312        if ( nl_ex == 0p ) return false;
     313       
     314        // otherwise loop and throwResume all pending exceptions
     315        while ( nl_ex != 0p ){
     316            exception_t * ex = nl_ex->the_exception;
     317            free( nl_ex );
     318            throwResume *ex;
     319            nl_ex = pop_ehm_head( base_cor );
     320        }
     321       
     322        return true;
     323    }
     324
     325    // poll iff nonlocal ehm is enabled
     326    bool checked_poll( T & cor ) libcfa_public { return get_coroutine( cor )->ehm_state.ehm_enabled ? poll( cor ) : false; }
     327}
     328
     329// resume non local exception at receiver (i.e. enqueue in ehm buffer)
     330forall(exceptT &, T & | ehm_resume_at( exceptT, T ))
     331void resumeAt( T & receiver, exceptT & ex )  libcfa_public {
     332    coroutine$ * cor = get_coroutine( receiver );
     333    nonlocal_exception * nl_ex = alloc();
     334    (*nl_ex){ (exception_t *)&ex };
     335    lock( cor->ehm_state.buffer_lock __cfaabi_dbg_ctx2 );
     336    append( cor->ehm_state.ehm_buffer, nl_ex );
     337    unlock( cor->ehm_state.buffer_lock );
     338}
     339
    285340// Local Variables: //
    286341// mode: c //
  • libcfa/src/concurrency/coroutine.hfa

    rb4d2b3b r2fe64ba  
    1919#include "invoke.h"
    2020#include "../exception.hfa"
     21
     22//-----------------------------------------------------------------------------
     23// Type used to store and queue nonlocal exceptions on coroutines
     24struct nonlocal_exception {
     25    exception_t * the_exception;
     26    nonlocal_exception * next;
     27};
     28static inline void ?{} ( nonlocal_exception & this, exception_t * ex ) with(this) {
     29    the_exception = ex;
     30    next = 0p;
     31}
     32
     33static inline nonlocal_exception *& get_next( nonlocal_exception & this ) __attribute__((const)) {
     34    return this.next;
     35}
    2136
    2237//-----------------------------------------------------------------------------
     
    203218}
    204219
     220// non local ehm routines
     221forall(T & | is_coroutine(T)) {
     222    void enable_ehm( T & cor );
     223    void disable_ehm( T & cor );
     224    bool poll( T & cor );
     225    bool checked_poll( T & cor );
     226}
     227
     228// trait for exceptions able to be resumed at another coroutine
     229forall(exceptT &, T & | is_coroutine(T))
     230trait ehm_resume_at { void $throwResume(exceptT &); };
     231
     232forall(exceptT &, T & | ehm_resume_at( exceptT, T ))
     233void resumeAt( T & receiver, exceptT & ex );
     234
    205235// Local Variables: //
    206236// mode: c //
  • libcfa/src/concurrency/invoke.h

    rb4d2b3b r2fe64ba  
    7474        };
    7575
     76    struct nonlocal_ehm {
     77        // list of pending nonlocal exceptions
     78        __queue_t(struct nonlocal_exception) ehm_buffer;
     79
     80        // lock to protect the buffer
     81        struct __spinlock_t buffer_lock;
     82
     83        // enable/disabled flag
     84        bool ehm_enabled;
     85    };
     86
    7687        enum __Coroutine_State { Halted, Start, Primed, Blocked, Ready, Active, Cancelled, Halting };
    7788
     
    98109                struct _Unwind_Exception * cancellation;
    99110
     111        // Non-local exception handling information
     112        struct nonlocal_ehm ehm_state;
    100113        };
    101114        // Wrapper for gdb
Note: See TracChangeset for help on using the changeset viewer.