Skip to content

Async I O handling interface

John Skaller edited this page Nov 30, 2018 · 1 revision

When an async process has been completed by the demux event monitoring thread, the fthread which requested it has to be reactivated. To do this we use these:

finote_t

namespace flx { namespace async {
struct ASYNC_EXTERN finote_t
{
  virtual void signal()=0;
  virtual ~finote_t();
};

A finote_t is the interface that the demux thread needs to enact the finishing of its operation. It is supplied a finote_t object and on completion of the request calls the signal() method.

wakeup_fthread_t

class ASYNC_EXTERN wakeup_fthread_t : public finote_t
{
  ::flx::rtl::fthread_t *f;
  ::flx::pthread::bound_queue_t *q;
public:
  wakeup_fthread_t(::flx::pthread::bound_queue_t *q_a, ::flx::rtl::fthread_t *f_a);
  void signal () { q->enqueue(f); }
};

The wakeup_fthread_t class is the implementation of the finote_t class used to construct objects which cause the requesting fthread to be place in a specified queue of fthreads whose async requests have been completed. The constructor accepts the queue to use and the fthread. It is run by the requesting Felix thread.

The signal() function just puts the fthread in the specified queue. It is run by the demux thread.

Async requests

An async request is an object used by a fibre running in a Felix thread to ask the demux thread to perform an asynchronous operation such as a time delay or socket data transfer.

class ASYNC_EXTERN flx_driver_request_base {
    finote_t *fn;
    virtual bool start_async_op_impl() = 0;
public:
    flx_driver_request_base();
    virtual ~flx_driver_request_base(); // so destructors work

    // returns finished flag (async may fail or immediately finish)
    void start_async_op(finote_t *fn_a);
    void notify_finished();
};

After construction, the start_async_op() method is called, passing a finote_t.