Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,13 @@ t->SetCallback([](Task *self) -> mg::box::Coro {
sched.Post(t);
```

See more in `src/mg/sch/README.md`.
See more in [src/mg/sch/README.md](/src/mg/sch/README.md).

## `IOCore`

**IOCore** is a multi-threaded event-loop for asynchronous code execution and network IO. It is like `TaskScheduler`, the internal architecture and the API are very similar, but `IOCore`'s main use case is work with sockets and efficient IO. You can think of it as if each of your sockets (server, accepted sockets, client sockets) is like a very lightweight coroutine. See more in `src/mg/aio/README.md`.
**IOCore** is a multi-threaded event-loop for asynchronous code execution and network IO. It is like `TaskScheduler`, the internal architecture and the API are very similar, but `IOCore`'s main use case is work with sockets and efficient IO. You can think of it as if each of your sockets (server, accepted sockets, client sockets) is like a very lightweight coroutine.

See more in [src/mg/aio/README.md](/src/mg/aio/README.md).

A simple example:
```C++
Expand Down Expand Up @@ -198,5 +200,5 @@ If none of the proposed interception endpoints are needed, you can simply link w

See more details here:

- `src/mg/sch/README.md`
- `src/mg/aio/README.md`
- [src/mg/sch/README.md](/src/mg/sch/README.md)
- [src/mg/aio/README.md](/src/mg/aio/README.md)
4 changes: 2 additions & 2 deletions src/mg/aio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ private:
};
```

`IOCore` (`src/mg/aio/IOCore.h`) is the event-loop itself. `IOTask` (`src/mg/aio/IOTask.h`) is a task context which a socket can be attached to, or any other data of your choice. With a socket attached `IOTask` can do asynchronous IO. In addition to that it also has the task features - wakeup and deadlines, just like `Task` in `TaskScheduler`.
`IOCore` ([src/mg/aio/IOCore.h](/src/mg/aio/IOCore.h)) is the event-loop itself. `IOTask` ([src/mg/aio/IOTask.h](/src/mg/aio/IOTask.h)) is a task context which a socket can be attached to, or any other data of your choice. With a socket attached `IOTask` can do asynchronous IO. In addition to that it also has the task features - wakeup and deadlines, just like `Task` in `TaskScheduler`.

For convenience some of the most popular socket types are already implemented on top of `IOTask`, such as `TCPSocket` (`src/mg/aio/TCPSocket.h`) for pure TCP interaction and `TCPServer` (`src/mg/aio/TCPServer.h`) for accepting new clients.
For convenience some of the most popular socket types are already implemented on top of `IOTask`, such as `TCPSocket` ([src/mg/aio/TCPSocket.h](/src/mg/aio/TCPSocket.h)) for pure TCP interaction and `TCPServer` ([src/mg/aio/TCPServer.h](/src/mg/aio/TCPServer.h)) for accepting new clients.

For building more specific sockets you can use those as a basis, or directly inherit `TCPSocketIFace`.

Expand Down
6 changes: 3 additions & 3 deletions src/mg/sch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -323,15 +323,15 @@ The scheduler is not a single monolithic algorithm. It is fused from several sma

### Multi-Producer-Single-Consumer Queue

The scheduler receives tasks from the external code via a front queue. It is an unbounded lock-free MPSC queue. See `src/mg/box/MultiProducerQueueIntrusive.h`.
The scheduler receives tasks from the external code via a front queue. It is an unbounded lock-free MPSC queue. See [src/mg/box/MultiProducerQueueIntrusive.h](/src/mg/box/MultiProducerQueueIntrusive.h).

Push is an atomic compare-exchange which in case of simultaneous access by multiple threads is retried. No spinlocks, nor any mutexes.

Pop is only able to take all the tasks at once and the order is reversed. That is the price of it being lock-free, a single atomic exchange. Basically, this queue is a stack, not a list. The order is restored back to normal when the scheduler processes the popped items.

### Multi-Consumer-Single-Producer Queue

This is a backend queue of the scheduler. From here the worker threads pick up the tasks ready for execution. It is an unbounded semi-lock-free MCSP queue. See `src/mg/box/MultiConsumerQueue.h`.
This is a backend queue of the scheduler. From here the worker threads pick up the tasks ready for execution. It is an unbounded semi-lock-free MCSP queue. See [src/mg/box/MultiConsumerQueue.h](/src/mg/box/MultiConsumerQueue.h).

There is no a simple well known algorithm for having multiple consumers which would be at the same time wait-free; lock-free; unbounded; and with ability to pop items one by one. Mostly that is because of the ABA problem of concurrent algorithms. Working them around usually is quite untrivial and can cost notable fraction of performance.

Expand Down Expand Up @@ -380,7 +380,7 @@ Linux WSL 1:

### Signal

Signal is a thread synchronization type, similar to mutex and condition variable. It allows to send an event from one thread to another in a blocking way, but it has a few most common cases optimized to be lock-free. See `src/mg/box/Signal.h`.
Signal is a thread synchronization type, similar to mutex and condition variable. It allows to send an event from one thread to another in a blocking way, but it has a few most common cases optimized to be lock-free. See [src/mg/box/Signal.h](/src/mg/box/Signal.h).

The scheduler uses it to
- Notify the worker threads about new ready-to-do tasks coming;
Expand Down
Loading