text:
package com.linkedin.kafka.cruisecontrol.async;

import com.linkedin.kafka.cruisecontrol.KafkaCruiseControl;
import com.linkedin.kafka.cruisecontrol.analyzer.GoalOptimizer;
import com.linkedin.kafka.cruisecontrol.monitor.ModelCompletenessRequirements;
import java.util.Collection;
import java.util.List;

/**
 * The async runnable for {@link KafkaCruiseControl#decommissionBrokers(Collection, boolean, boolean, List,
 * ModelCompletenessRequirements, com.linkedin.kafka.cruisecontrol.async.progress.OperationProgress)}
 */
class DecommissionBrokersRunnable extends OperationRunnable<GoalOptimizer.OptimizerResult> {
  private final Collection<Integer> _brokerIds;
  private final boolean _dryRun;
  private final boolean _throttleRemovedBrokers;
  private final List<String> _goals;
  private final ModelCompletenessRequirements _modelCompletenessRequirements;

  DecommissionBrokersRunnable(KafkaCruiseControl kafkaCruiseControl,
                              OperationFuture<GoalOptimizer.OptimizerResult> future,
                              Collection<Integer> brokerIds,
                              boolean dryRun,
                              boolean throttleRemovedBrokers,
                              List<String> goals,
                              ModelCompletenessRequirements modelCompletenessRequirements) {
    super(kafkaCruiseControl, future);
    _brokerIds = brokerIds;
    _dryRun = dryRun;
    _throttleRemovedBrokers = throttleRemovedBrokers;
    _goals = goals;
    _modelCompletenessRequirements = modelCompletenessRequirements;
  }

  @Override
  protected GoalOptimizer.OptimizerResult getResult() throws Exception {
    return _kafkaCruiseControl.decommissionBrokers(_brokerIds, _dryRun, _throttleRemovedBrokers, _goals,
                                                   _modelCompletenessRequirements, _future.operationProgress());
  }
}


text:
struct TRI_datafile_s;
struct TRI_df_marker_s;
struct TRI_document_collection_t;
struct TRI_server_s;

namespace triagens {
  namespace wal {

    class LogfileManager;
    class Logfile;

// -----------------------------------------------------------------------------
// --SECTION--                                         struct CollectorOperation
// -----------------------------------------------------------------------------

    struct CollectorOperation {
      CollectorOperation (char const* datafilePosition,
                          TRI_voc_size_t datafileMarkerSize,
                          char const* walPosition,
                          TRI_voc_fid_t datafileId)
        : datafilePosition(datafilePosition),
          datafileMarkerSize(datafileMarkerSize),
          walPosition(walPosition),
          datafileId(datafileId) {
        TRI_ASSERT_EXPENSIVE(datafilePosition != nullptr);
        TRI_ASSERT_EXPENSIVE(datafileMarkerSize > 0);
        TRI_ASSERT_EXPENSIVE(walPosition != nullptr);
        TRI_ASSERT_EXPENSIVE(datafileId > 0);
      }

      char const*     datafilePosition;
      TRI_voc_size_t  datafileMarkerSize;
      char const*     walPosition;
      TRI_voc_fid_t   datafileId;
    };

// -----------------------------------------------------------------------------
// --SECTION--                                             struct CollectorCache
// -----------------------------------------------------------------------------

    struct CollectorCache {
      CollectorCache (CollectorCache const&) = delete;
      CollectorCache& operator= (CollectorCache const&) = delete;

      explicit CollectorCache (TRI_voc_cid_t collectionId,
                               TRI_voc_tick_t databaseId,
                               Logfile* logfile,
                               int64_t totalOperationsCount,
                               size_t operationsSize)
        : collectionId(collectionId),
          databaseId(databaseId),
          logfile(logfile),
          totalOperationsCount(totalOperationsCount),
          operations(new std::vector<CollectorOperation>()),
          barriers(),
          dfi(),
          lastFid(0),
          lastDatafile(nullptr) {

        operations->reserve(operationsSize);
      }

      ~CollectorCache () {
        if (operations != nullptr) {
          delete operations;
        }
        freeBarriers();
      }

////////////////////////////////////////////////////////////////////////////////
/// @brief add a barrier
////////////////////////////////////////////////////////////////////////////////

      void addBarrier (TRI_barrier_t* barrier) {
        TRI_ASSERT(barrier != nullptr);
        barriers.push_back(barrier);
      }

////////////////////////////////////////////////////////////////////////////////
/// @brief free all barriers
////////////////////////////////////////////////////////////////////////////////

      void freeBarriers () {
        for (auto it = barriers.begin(); it != barriers.end(); ++it) {
          TRI_FreeBarrier((*it));
        }

        barriers.clear();
      }

////////////////////////////////////////////////////////////////////////////////
/// @brief id of collection
////////////////////////////////////////////////////////////////////////////////

      TRI_voc_cid_t const collectionId;

////////////////////////////////////////////////////////////////////////////////
/// @brief id of database
////////////////////////////////////////////////////////////////////////////////

      TRI_voc_tick_t const databaseId;

////////////////////////////////////////////////////////////////////////////////
/// @brief id of the WAL logfile
////////////////////////////////////////////////////////////////////////////////

      Logfile* logfile;

////////////////////////////////////////////////////////////////////////////////
/// @brief total number of operations in this block
////////////////////////////////////////////////////////////////////////////////

      int64_t const totalOperationsCount;

////////////////////////////////////////////////////////////////////////////////
/// @brief all collector operations of a collection
////////////////////////////////////////////////////////////////////////////////

      std::vector<CollectorOperation>* operations;

////////////////////////////////////////////////////////////////////////////////
/// @brief barriers held by the operations
////////////////////////////////////////////////////////////////////////////////

      std::vector<TRI_barrier_t*> barriers;

////////////////////////////////////////////////////////////////////////////////
/// @brief datafile info cache, updated when the collector transfers markers
////////////////////////////////////////////////////////////////////////////////

      std::unordered_map<TRI_voc_fid_t, TRI_doc_datafile_info_t> dfi;

////////////////////////////////////////////////////////////////////////////////
/// @brief id of last datafile handled
////////////////////////////////////////////////////////////////////////////////

      TRI_voc_fid_t lastFid;

////////////////////////////////////////////////////////////////////////////////
/// @brief last datafile written to
////////////////////////////////////////////////////////////////////////////////

      TRI_datafile_t* lastDatafile;
    };

// -----------------------------------------------------------------------------
// --SECTION--                                             class CollectorThread
// -----------------------------------------------------------------------------

    class CollectorThread : public basics::Thread {

////////////////////////////////////////////////////////////////////////////////
/// @brief CollectorThread
////////////////////////////////////////////////////////////////////////////////

      private:
        CollectorThread (CollectorThread const&) = delete;
        CollectorThread& operator= (CollectorThread const&) = delete;

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

      public:

////////////////////////////////////////////////////////////////////////////////
/// @brief create the collector thread
////////////////////////////////////////////////////////////////////////////////

        CollectorThread (LogfileManager*,
                         struct TRI_server_s*);

////////////////////////////////////////////////////////////////////////////////
/// @brief destroy the collector thread
////////////////////////////////////////////////////////////////////////////////

        ~CollectorThread ();

// -----------------------------------------------------------------------------
// --SECTION--                                                   public typedefs
// -----------------------------------------------------------------------------

      public:

////////////////////////////////////////////////////////////////////////////////
/// @brief typedef key => document marker
////////////////////////////////////////////////////////////////////////////////

        typedef std::unordered_map<std::string, struct TRI_df_marker_s const*> DocumentOperationsType;

////////////////////////////////////////////////////////////////////////////////
/// @brief typedef for structural operation (attributes, shapes) markers
////////////////////////////////////////////////////////////////////////////////

        typedef std::vector<struct TRI_df_marker_s const*> OperationsType;

// -----------------------------------------------------------------------------
// --SECTION--                                                    public methods
// -----------------------------------------------------------------------------

      public:

////////////////////////////////////////////////////////////////////////////////
/// @brief stops the collector thread
////////////////////////////////////////////////////////////////////////////////

        void stop ();

////////////////////////////////////////////////////////////////////////////////
/// @brief signal the thread that there is something to do
////////////////////////////////////////////////////////////////////////////////

        void signal ();

// -----------------------------------------------------------------------------
// --SECTION--                                                    Thread methods
// -----------------------------------------------------------------------------

      protected:

////////////////////////////////////////////////////////////////////////////////
/// @brief main loop
////////////////////////////////////////////////////////////////////////////////

        void run ();

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

      private:

////////////////////////////////////////////////////////////////////////////////
/// @brief check whether there are queued operations left
////////////////////////////////////////////////////////////////////////////////

        bool hasQueuedOperations ();

////////////////////////////////////////////////////////////////////////////////
/// @brief return the number of queued operations
////////////////////////////////////////////////////////////////////////////////

        size_t numQueuedOperations ();

////////////////////////////////////////////////////////////////////////////////
/// @brief step 1: perform collection of a logfile (if any)
////////////////////////////////////////////////////////////////////////////////

        bool collectLogfiles ();

////////////////////////////////////////////////////////////////////////////////
/// @brief step 2: process all still-queued collection operations
////////////////////////////////////////////////////////////////////////////////

        bool processQueuedOperations ();

////////////////////////////////////////////////////////////////////////////////
/// @brief process all operations for a single collection
////////////////////////////////////////////////////////////////////////////////

        int processCollectionOperations (CollectorCache*);

////////////////////////////////////////////////////////////////////////////////
/// @brief collect one logfile
////////////////////////////////////////////////////////////////////////////////

        int collect (Logfile*);

////////////////////////////////////////////////////////////////////////////////
/// @brief transfer markers into a collection
////////////////////////////////////////////////////////////////////////////////

        int transferMarkers (triagens::wal::Logfile*,
                             TRI_voc_cid_t,
                             TRI_voc_tick_t,
                             int64_t,
                             OperationsType const&);

////////////////////////////////////////////////////////////////////////////////
/// @brief transfer markers into a collection
////////////////////////////////////////////////////////////////////////////////

        int executeTransferMarkers (TRI_document_collection_t*,
                                    CollectorCache*,
                                    OperationsType const&);

////////////////////////////////////////////////////////////////////////////////
/// @brief insert the collect operations into a per-collection queue
////////////////////////////////////////////////////////////////////////////////

        int queueOperations (triagens::wal::Logfile*,
                             CollectorCache*&);

////////////////////////////////////////////////////////////////////////////////
/// @brief update a collection's datafile information
////////////////////////////////////////////////////////////////////////////////

        int updateDatafileStatistics (TRI_document_collection_t*,
                                      CollectorCache*);

////////////////////////////////////////////////////////////////////////////////
/// @brief sync the journals of a collection
////////////////////////////////////////////////////////////////////////////////

        int syncDatafileCollection (struct TRI_document_collection_t*);

////////////////////////////////////////////////////////////////////////////////
/// @brief get the next free position for a new marker of the specified size
////////////////////////////////////////////////////////////////////////////////

        char* nextFreeMarkerPosition (struct TRI_document_collection_t*,
                                      TRI_voc_tick_t,
                                      TRI_df_marker_type_e,
                                      TRI_voc_size_t,
                                      CollectorCache*);

////////////////////////////////////////////////////////////////////////////////
/// @brief initialise a marker
////////////////////////////////////////////////////////////////////////////////

        void initMarker (struct TRI_df_marker_s*,
                         TRI_df_marker_type_e,
                         TRI_voc_size_t);

////////////////////////////////////////////////////////////////////////////////
/// @brief set the tick of a marker and calculate its CRC value
////////////////////////////////////////////////////////////////////////////////

        void finishMarker (char const*,
                           char*,
                           struct TRI_document_collection_t*,
                           TRI_voc_tick_t,
                           CollectorCache*);

// -----------------------------------------------------------------------------
// --SECTION--                                                 private variables
// -----------------------------------------------------------------------------

      private:

////////////////////////////////////////////////////////////////////////////////
/// @brief the logfile manager
////////////////////////////////////////////////////////////////////////////////

        LogfileManager* _logfileManager;

////////////////////////////////////////////////////////////////////////////////
/// @brief pointer to the server
////////////////////////////////////////////////////////////////////////////////

        struct TRI_server_s* _server;

////////////////////////////////////////////////////////////////////////////////
/// @brief condition variable for the collector thread
////////////////////////////////////////////////////////////////////////////////

        basics::ConditionVariable _condition;

////////////////////////////////////////////////////////////////////////////////
/// @brief operations lock
////////////////////////////////////////////////////////////////////////////////

        triagens::basics::Mutex _operationsQueueLock;

////////////////////////////////////////////////////////////////////////////////
/// @brief operations to collect later
////////////////////////////////////////////////////////////////////////////////

        std::unordered_map<TRI_voc_cid_t, std::vector<CollectorCache*>> _operationsQueue;

////////////////////////////////////////////////////////////////////////////////
/// @brief whether or not the queue is currently in use
////////////////////////////////////////////////////////////////////////////////

        bool _operationsQueueInUse;

////////////////////////////////////////////////////////////////////////////////
/// @brief stop flag
////////////////////////////////////////////////////////////////////////////////

        volatile sig_atomic_t _stop;

////////////////////////////////////////////////////////////////////////////////
/// @brief number of pending operations in collector queue
////////////////////////////////////////////////////////////////////////////////

        uint64_t _numPendingOperations;

////////////////////////////////////////////////////////////////////////////////
/// @brief wait interval for the collector thread when idle
////////////////////////////////////////////////////////////////////////////////

        static uint64_t const Interval;

    };

  }
}

#endif

// -----------------------------------------------------------------------------
// --SECTION--                                                       END-OF-FILE
// -----------------------------------------------------------------------------

// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End:

redpajama_set_name: RedPajamaGithub


text:
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';

import { ElasticModule } from 'angular2-elastic';

import { AppComponent } from './app.component';
import { HomePage } from '../pages/home/home';
import { DreamDetailPage } from '../pages/dream-detail/dream-detail';
import { DreamFormPage } from '../pages/dream-form/dream-form';
import { DreamPopoverPage } from '../pages/dream-popover/dream-popover';
import { DreamService } from '../providers/dream.service';

/**
 * Root module.
 *
 * @export
 * @class AppModule
 */
@NgModule({
    declarations: [
        AppComponent,
        HomePage,
        DreamDetailPage,
        DreamFormPage,
        DreamPopoverPage
    ],
    imports: [
        IonicModule.forRoot(AppComponent, {
            statusbarPadding: false
        }),
        ElasticModule
    ],
    bootstrap: [IonicApp],
    entryComponents: [
        AppComponent,
        HomePage,
        DreamDetailPage,
        DreamFormPage,
        DreamPopoverPage
    ],
    providers: [
        { provide: ErrorHandler, useClass: IonicErrorHandler },
        DreamService
    ]
})
export class AppModule {
}


text:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <ExpandableListView
        android:id="@+id/sent_list"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:groupIndicator="@null">
    </ExpandableListView>
</RelativeLayout>


text:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_single_download"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/titleTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:textSize="24sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:text="Title" />

    <TextView
        android:id="@+id/progressTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:textSize="42sp"
        app:layout_constraintEnd_toEndOf="@+id/titleTextView"
        app:layout_constraintStart_toStartOf="@+id/titleTextView"
        app:layout_constraintTop_toBottomOf="@+id/titleTextView"
        tools:text="65%" />

    <TextView
        android:id="@+id/etaTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/progressTextView"
        tools:text="10s" />

    <TextView
        android:id="@+id/downloadSpeedTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/etaTextView"
        tools:text="204 KB/s" />

</android.support.constraint.ConstraintLayout>


text:
function Person(){}
Person.prototype.getName = function(){
  return this.name;
};

function Me(){
  this.name = "John Resig";
}
Me.prototype = new Person();

var me = new Me();
assert( me.getName() );


text:
This document aims to explain the operation of `uasyncio` as I understand it. I
did not write the library so the information presented is a result of using it,
studying the code, experiment and inference. There may be errors, in which case
please raise an issue. None of this information is required to use the library:
it is intended to satisfy the curiosity of scheduler geeks or to help those
wishing to modify it.

# 0. Contents

 1. [Introduction](./UNDER_THE_HOOD.md#1-introduction)
 2. [Generators and coroutines](./UNDER_THE_HOOD.md#2-generators-and-coroutines)
  2.1 [pend_throw](./UNDER_THE_HOOD.md#21-pend_throw)
 3. [Coroutine yield types](./UNDER_THE_HOOD.md#3-coroutine-yield-types)
  3.1 [SysCall1 classes](./UNDER_THE_HOOD.md#31-syscall1-classes)
 4. [The EventLoop](./UNDER_THE_HOOD.md#4-the-eventloop)
  4.1 [Exceptions](./UNDER_THE_HOOD.md#41-exceptions)
  4.2 [Task Cancellation and Timeouts](./UNDER_THE_HOOD.md#42-task-cancellation-and-timeouts)
 5. [Stream I/O](./UNDER_THE_HOOD.md#5-stream-io)
  5.1 [StreamReader](./UNDER_THE_HOOD.md#51-streamreader)
  5.2 [StreamWriter](./UNDER_THE_HOOD.md#52-streamwriter)
  5.3 [PollEventLoop wait method](./UNDER_THE_HOOD.md#53-polleventloop-wait-method)
 6. [Modifying uasyncio](./UNDER_THE_HOOD.md#6-modifying-uasyncio)
 7. [Links](./UNDER_THE_HOOD.md#7-links)

# 1. Introduction

Where the versions differ, this explanation relates to the `fast_io` version.
Note that the code in `fast_io` contains additional comments to explain its
operation. The code the `fast_io` directory is also in
[my micropython-lib fork](https://github.com/peterhinch/micropython-lib.git),
`uasyncio-io-fast-and-rw` branch.

This doc assumes a good appreciation of the use of `uasyncio`. An understanding
of Python generators is also essential, in particular the use of `yield from`
and an appreciation of the difference between a generator and a generator
function:

```python
def gen_func(n):  # gen_func is a generator function
    while True:
        yield n
        n += 1

my_gen = gen_func(7)  # my_gen is a generator
```

The code for the `fast_io` variant of `uasyncio` may be found in:

```
fast_io/__init__.py
fast_io/core.py
```

This has additional code comments to aid in its understanding.

###### [Main README](./README.md)

# 2. Generators and coroutines

In MicroPython coroutines and generators are identical: this differs from
CPython. The knowledge that a coro is a generator is crucial to understanding
`uasyncio`'s operation. Consider this code fragment:

```python
async def bar():
    await asyncio.sleep(1)

async def foo():
    await bar()
```

In MicroPython the `async def` syntax allows a generator function to lack a
`yield` statement. Thus `bar` is a generator function, hence `bar()` returns a
generator.

The `await bar()` syntax is equivalent to `yield from bar()`. So transferring
execution to the generator instantiated by `bar()` does not involve the
scheduler. `asyncio.sleep` is a generator function so `await asyncio.sleep(1)`
creates a generator and transfers execution to it via `yield from`. The
generator yields a value of 1000; this is passed to the scheduler to invoke the
delay by placing the coro onto a `timeq` (see below).

## 2.1 pend_throw

Generators in MicroPython have a nonstandard method `pend_throw`. The Python
`throw` method causes the generator immediately to run and to handle the passed
exception. `pend_throw` retains the exception until the generator (coroutine)
is next scheduled, when the exception is raised. In `fast_io` the task
cancellation and timeout mechanisms aim to ensure that the task is scheduled as
soon as possible to minimise latency.

The `pend_throw` method serves a secondary purpose in `uasyncio`: to store
state in a coro which is paused pending execution. This works because the
object returned from `pend_throw` is that which was previously passed to it, or
`None` on the first call.

```python
a = my_coro.pend_throw(42)
b = my_coro.pend_throw(None)  # Coro can now safely be executed
```
In the above instance `a` will be `None` if it was the first call to
`pend_throw` and `b` will be 42. This is used to determine if a paused task is
on a `timeq` or waiting on I/O. A task on a `timeq` will have an integer value,
being the `ID` of the task; one pending I/O will have `False`.

If a coro is actually run, the only acceptable stored values are `None` or an
exception. The error "exception must be derived from base exception" indicates
an error in the scheduler whereby this constraint has not been satisfied.

###### [Contents](./UNDER_THE_HOOD.md#0-contents)

# 3. Coroutine yield types

Because coroutines are generators it is valid to issue `yield` in a coroutine,
behaviour which would cause a syntax error in CPython. While explicitly issuing
`yield` in a user application is best avoided for CPython compatibility, it is
used internally in `uasyncio`. Further, because `await` is equivalent to
`yield from`, the behaviour of the scheduler in response to `yield` is crucial
to understanding its operation.

Where a coroutine (perhaps at the end of a `yield from` chain) executes

```python
yield some_object
```

the scheduler regains execution. This is because the scheduler passed execution
to the user coroutine with

```python
ret = next(cb)
```

so `ret` contains the object yielded. Subsequent scheduler behaviour depends on
the type of that object. The following object types are handled:

 * `None` The coro is rescheduled and will run in round-robin fashion.
 Hence `yield` is functionally equivalent to `await asyncio.sleep(0)`.
 * An integer `N`: equivalent to `await asyncio.sleep_ms(N)`.
 * `False` The coro terminates and is not rescheduled.
 * A coro/generator: the yielded coro is scheduled. The coro which issued the
 `yield` is rescheduled.
 * A `SysCall1` instance. See below.

## 3.1 SysCall1 classes

The `SysCall1` constructor takes a single argument stored in `self.arg`. It is
effectively an abstract base class: only subclasses are instantiated. When a
coro yields a `SysCall1` instance, the scheduler's behaviour is determined by
the type of the object and the contents of its `.arg`.

The following subclasses exist:

 * `SleepMs` `.arg` holds the delay in ms. Effectively a singleton with the
 instance in `sleep_ms`. Its `.__call__` enables `await asyncio.sleep_ms(n)`.
 * `StopLoop` Stops the scheduler. `.arg` is returned to the caller.
 * `IORead` Causes an interface to be polled for data ready. `.arg` is the
 interface.
 * `IOWrite` Causes an interface to be polled for ready to accept data. `.arg`
 is the interface.
 * `IOReadDone` These stop polling of an interface (in `.arg`).
 * `IOWriteDone`

The `IO*` classes are for the exclusive use of `StreamReader` and `StreamWriter`
objects.

###### [Contents](./UNDER_THE_HOOD.md#0-contents)

# 4. The EventLoop

The file `core.py` defines an `EventLoop` class which is subclassed by
`PollEventLoop` in `__init__.py`. The latter extends the base class to support
stream I/O. In particular `.wait()` is overridden in the subclass.

The `fast_io` `EventLoop` maintains four queues, `.runq`, `.waitq`, `.lpq` and
`.ioq`. The latter two are only instantiated if specified to the
`get_event_loop` method. Official `uasyncio` does not have `.lpq` or `.ioq`.

Tasks are appended to the bottom of the run queue and retrieved from the top;
in other words it is a First In First Out (FIFO) queue. The I/O queue is
similar. Tasks on `.waitq` and `.lpq` are sorted in order of the time when they
are to run, the task having the soonest time to run at the top.

When a task issues `await asyncio.sleep(t)` or `await asyncio.sleep_ms(t)` and
t > 0 the task is placed on the wait queue. If t == 0 it is placed on the run
queue (by `.call_soon()`). Callbacks are placed on the queues in a similar way
to tasks.

The following is a somewhat broad-brush explanation of an iteration of the
event loop's `run_forever()` method intended to aid in following the code.

The method first checks the wait queue. Any tasks which have become due (or
overdue) are removed and placed on the run queue.

The run queue is then processed. The number of tasks on it is determined: only
that number of tasks will be run. Because the run queue is FIFO this guarantees
that exactly those tasks which were on the queue at the start of processing
this queue will run (even when tasks are appended).

The topmost task/callback is removed and run. If it is a callback the loop
iterates to the next entry. If it is a task, it runs then either yields or
raises an exception. If it yields, the return type is examined as described
above. If the task yields with a zero delay it will be appended to the run
queue, but as described above it will not be rescheduled in this pass through
the queue. If it yields a nonzero delay it will be added to `.waitq` (it has
already been removed from `.runq`).

Once every task which was initially on the run queue has been scheduled, the
queue may or may not be empty depending on whether tasks yielded a zero delay.

At the end of the outer loop a `delay` value is determined. This will be zero
if the run queue is not empty: tasks are ready for scheduling. If the run queue
is empty `delay` is determined from the time to run of the topmost (most
current) task on the wait queue.

The `.wait()` method is called with this delay. If the delay is > 0 the
scheduler pauses for this period (polling I/O). On a zero delay I/O is checked
once: if nothing is pending it returns quickly.

###### [Contents](./UNDER_THE_HOOD.md#0-contents)

## 4.1 Exceptions

There are two "normal" cases where tasks raise an exception: when the task is
complete (`StopIteration`) and when it is cancelled (`CancelledError`). In both
these cases the exception is trapped and the loop proceeds to the next item on
the run queue - the task is simply not rescheduled.

If an unhandled exception occurs in a task this will be propagated to the
caller of `run_forever()` or `run_until_complete` a explained in the tutorial.

## 4.2 Task Cancellation and Timeouts

The `cancel` function uses `pend_throw` to pass a `CancelledError` to the coro
to be cancelled. The generator's `.throw` and `.close` methods cause the coro
to execute code immediately. This is incorrect behaviour for a de-scheduled
coro. The `.pend_throw` method causes the exception to be processed the next
time the coro is scheduled.

In the `fast_io` version the `cancel` function puts the task onto `.runq` or
`.ioq` for "immediate" excecution. In the case where the task is on `.waitq` or
`.lpq` the task ID is added to a `set` `.canned`. When the task reaches the top
of the timeq it is ignored and removed from `.canned`. This Python approach is
less efficient than that in the Paul Sokolovsky fork, but his approach uses a
special version of the C `utimeq` object and so requires his firmware.

Timeouts use a similar mechanism.

###### [Contents](./UNDER_THE_HOOD.md#0-contents)

# 5. Stream IO

Stream I/O is an efficient way of polling stream devices using `select.poll`.
Device drivers for this mechanism must provide an `ioctl` method which reports
whether a read device has data ready, or whether a write device is capable of
accepting data. Stream I/O is handled via `StreamReader` and `StreamWriter`
instances (defined in `__init__.py`).

## 5.1 StreamReader

The class supports three read coros which work in a similar fashion. The coro
yields an `IORead` instance with the device to be polled as its arg. It is
rescheduled when `ioctl` has reported that some data is available. The coro
reads the device by calling the device driver's `read` or `readline` method.
If all available data has been read, the device's read methods must update the
status returned by its `ioctl` method.

The `StreamReader` read coros iterate until the required data has been read,
when the coro yields `IOReadDone(object_to_poll)` before returning the data. If
during this process, `ioctl` reports that no data is available, the coro
yields `IORead(object_to_poll)`. This causes the coro to be descheduled until
data is again available.

The mechanism which causes it to be rescheduled is discussed below (`.wait()`).

When `IORead(object_to_poll)` is yielded the `EventLoop` calls `.add_reader()`.
This registers the device with `select.poll` as a reader, and saves the coro
for later rescheduling.

The `PollEventLoop` maintains three dictionaries indexed by the `id` of the
object being polled. These are:

 * `rdobjmap` Value: the suspended read coro.
 * `wrobjmap` Value: the suspended write coro (read and write coros may both be
 in a suspended state).
 * `flags` Value: bitmap of current poll flags.

The `add_reader` method saves the coro in `.rdobjmap` and updates `.flags` and
the poll flags so that `ioctl` will respond to a `MP_STREAM_POLL_RD` query.

When the `StreamReader` read method completes it yields
`IOReadDone(object_to_poll)`: this updates `.flags` and the poll flags so that
`ioctl` no longer responds to an `MP_STREAM_POLL_RD` query.

## 5.2 StreamWriter

This supports the `awrite` coro which works in a similar way to `StreamReader`,
yielding `IOWrite(object_to_poll)` until all data has been written, followed
by `IOWriteDone(object_to_poll)`.

The mechanism is the same as for reading, except that when `ioctl` returns a
"ready" state for a writeable device it means the device is capable of writing
at least one character.

## 5.3 PollEventLoop wait method

When this is called the `Poll` instance is checked in a one-shot mode. In this
mode it will return either when `delay` has elapsed or when at least one device
is ready.

The poller's `ipoll` method uses the iterator protocol to return successive
`(sock, ev)` tuples where `sock` is the device driver and `ev` is a bitmap of
read and write ready status for that device. The `.wait` method iterates
through each device requiring service.

If the read bit is set (i.e. `ioctl` reported data available) the read coro is
retrieved from `.rdobjmap` and queued for scheduling. This is done via
`._call_io`: this puts the coro onto `.runq` or `.ioq` depending on whether an
I/O queue has been instantiated.

Writing is handled similarly.

###### [Contents](./UNDER_THE_HOOD.md#0-contents)

# 6. Modifying uasyncio

The library is designed to be extensible. By following these guidelines a
module can be constructed which alters the functionality of asyncio without the
need to change the official library. Such a module may be used where `uasyncio`
is implemented as frozen bytecode as in official release binaries.

Assume that the aim is to alter the event loop. The module should issue

```python
from uasyncio import *
```

The event loop should be subclassed from `PollEventLoop` (defined in
`__init__.py`).

The event loop is instantiated by the first call to `get_event_loop()`: this
creates a singleton instance. This is returned by every call to
`get_event_loop()`. On the assumption that the constructor arguments for the
new class differ from those of the base class, the module will need to redefine
`get_event_loop()` along the following lines:

```python
_event_loop = None  # The singleton instance
_event_loop_class = MyNewEventLoopClass  # The class, not an instance
def get_event_loop(args):
    global _event_loop
    if _event_loop is None:
        _event_loop = _event_loop_class(args)  # Instantiate once only
    return _event_loop
```

###### [Contents](./UNDER_THE_HOOD.md#0-contents)

# 7. Links

Initial discussion of priority I/O scheduling [here](https://github.com/micropython/micropython/issues/2664).

MicroPython PR enabling stream device drivers to be written in Python
[PR #3836: io.IOBase](https://github.com/micropython/micropython/pull/3836).
Includes discussion of the read/write bug.

My outstanding uasyncio PR's: fast I/O
[PR #287](https://github.com/micropython/micropython-lib/pull/287) improved
error reporting
[PR #292](https://github.com/micropython/micropython-lib/pull/292).

This caught my attention for usefulness and compliance with CPython:
[PR #270](https://github.com/micropython/micropython-lib/pull/270).

###### [Main README](./README.md)


text:
import { ModalDirective } from 'ng2-bootstrap/modal';
import { LineChartComponent } from '../../charts';
import { BaseModalComponent } from '../base-modal/base-modal.component';
import { ModalComponentData } from '../modal-component-data.interface';
import {
  AfterViewInit,
  Component,
  ComponentFactoryResolver,
  Injector,
  Input,
  OnDestroy,
  ReflectiveInjector,
  ViewChild,
  ViewContainerRef
} from '@angular/core';

@Component({
  selector: 'app-chart-modal',
  templateUrl: './chart-modal.component.html',
  styleUrls: ['./chart-modal.component.sass'],
})
export class ChartModalComponent extends BaseModalComponent implements AfterViewInit, OnDestroy {
  private _currentComponent = null;

  @Input('title') title = 'Chart Title';
  @Input('chartOptions') chartOptions: ModalComponentData;
  @ViewChild('contentModal') contentModal: ModalDirective;
  @ViewChild('chartContainer', { read: ViewContainerRef }) chartContainer: ViewContainerRef;

  constructor(
    private _resolver: ComponentFactoryResolver,
    injector: Injector
  ) {
    // call the parent constructor
    super(injector);

    // retrieve properties from the injector
    this.title = injector.get('title', 'Chart Title');
    this.chartOptions = injector.get('chartOptions', null);
  }

  onHide() {
    super.onHide();
  }

  onShow() {
    super.onShow();
  }

  ngAfterViewInit() {
    let resolvedInputs = [];

    // call the parent ngAfterViewInit()
    super.ngAfterViewInit();

    // dont create any chart components when component metadata is not specified or provided.
    if (typeof this.chartOptions === 'undefined' || this.chartOptions === null) {
      return;
    }

    if (typeof this.chartOptions.inputs !== 'undefined') {
      // Inputs need to be in the following format to be resolved properly
      const inputProviders = Object
        .keys(this.chartOptions.inputs)
        .map((inputName: string) => {
          return {
            provide: inputName,
            useValue: this.chartOptions.inputs[inputName]
          };
        })
        ;

      resolvedInputs = ReflectiveInjector.resolve(inputProviders);
    }

    // We create an injector out of the data we want to pass down and this components injector
    const injector = ReflectiveInjector.fromResolvedProviders(resolvedInputs, this.chartContainer.parentInjector);

    // We create a factory out of the component we want to create
    const factory = this._resolver.resolveComponentFactory((this.chartOptions as any).type);

    // We create the component using the factory and the injector
    const component = factory.create(injector);

    // enable change detection in the component
    component.changeDetectorRef.detectChanges();

    // clean up everything when component is destroyed
    component.onDestroy(() => {
      component.changeDetectorRef.detach();
    });

    // We insert the component into the dom container
    this.chartContainer.insert(component.hostView);

    // save the current component
    this._currentComponent = component;
  }

  ngOnDestroy() {
    // destroy the dynamically created component when it is not null
    if (this._currentComponent !== null) {
      this._currentComponent.destroy();
    }
  }

}