# Synchronizer

<a id="synchronizer"></a>

# Synchronizer

```cpp
#include <icy/synchronizer.h>

class Synchronizer
```

[Defined in src/base/include/icy/synchronizer.h:39](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L39)

> **Inherits:** [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner)

[Synchronizer](#synchronizer) enables any thread to communicate with the associated event loop via synchronized callbacks.

This class inherits the [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) interface and may be used with any implementation that's powered by an asynchronous [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner).

## List of all members

| Name | Kind | Owner |
|------|------|-------|
| [`Synchronizer`](#synchronizer-1) | `function` | Declared here |
| [`Synchronizer`](#synchronizer-2) | `function` | Declared here |
| [`Synchronizer`](#synchronizer-3) | `function` | Declared here |
| [`~Synchronizer`](#synchronizer-4) | `function` | Declared here |
| [`post`](#post) | `function` | Declared here |
| [`start`](#start-5) | `function` | Declared here |
| [`start`](#start-6) | `function` | Declared here |
| [`cancel`](#cancel-3) | `function` | Declared here |
| [`close`](#close-6) | `function` | Declared here |
| [`handle`](#handle-2) | `function` | Declared here |
| [`_handle`](#_handle-2) | `variable` | Declared here |
| [`_postMutex`](#_postmutex) | `variable` | Declared here |
| [`async`](#async-2) | `function` | Declared here |
| [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner-1) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`~Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner-2) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`start`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#start-3) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`running`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#running) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`cancel`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#cancel-2) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`cancelled`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#cancelled-1) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`repeating`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#repeating) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`setRepeating`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#setrepeating) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`async`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#async-1) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`tid`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#tid) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`waitForExit`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#waitforexit) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`_context`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#_context) | `variable` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner-3) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`operator=`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#operator-81) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner-4) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |
| [`operator=`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#operator-82) | `function` | Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) |

## Inherited from [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner)

| Kind | Name | Description |
|------|------|-------------|
| `function` | [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner-1)  |  |
| `function` | [`~Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner-2) `virtual` |  |
| `function` | [`start`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#start-3) `virtual` | Starts the asynchronous context with the given callback. The callback must remain valid for the lifetime of the [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner). |
| `function` | [`running`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#running) `const` | Returns true if the async context is currently running. |
| `function` | [`cancel`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#cancel-2)  | Signals the async context to stop at the earliest opportunity. |
| `function` | [`cancelled`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#cancelled-1) `const` | Returns true if the context has been cancelled. The implementation is responsible for exiting as soon as possible after cancellation. |
| `function` | [`repeating`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#repeating) `const` | Returns true if the runner is in repeating mode. |
| `function` | [`setRepeating`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#setrepeating)  | Enables or disables repeating mode. When repeating, the target function is invoked repeatedly until [`cancel()`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#cancel-2) is called. This normalizes behaviour across thread-based and event-loop-based [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner) implementations. Must be called before [`start()`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#start-3). |
| `function` | [`async`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#async-1) `virtual` `const` | Returns true if the implementation is thread-based. |
| `function` | [`tid`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#tid) `const` | Returns the native thread ID of the thread running the async context. |
| `function` | [`waitForExit`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#waitforexit)  | Blocks until the async context exits or the timeout elapses. The context should be cancelled before calling this method. Must be called from outside the runner's own thread to avoid deadlock. |
| `variable` | [`_context`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#_context)  | Shared pointer to the internal [Context](https://auscaster.com/icey/docs/api-reference/icy-Runner-Context.md#context). |
| `function` | [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner-3)  | NonCopyable and NonMovable. |
| `function` | [`operator=`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#operator-81)  | Deleted assignment operator. |
| `function` | [`Runner`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#runner-4)  | Deleted constructor. |
| `function` | [`operator=`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#operator-82)  | Deleted assignment operator. |

## Public Methods

| Return | Name | Description |
|--------|------|-------------|
|  | [`Synchronizer`](#synchronizer-1)  | Creates a synchronizer attached to the given event loop without a callback. Call [`start()`](#start-5) separately to register the callback before using [`post()`](#post). |
|  | [`Synchronizer`](#synchronizer-2)  | Creates and immediately starts a synchronizer with a single callback function. The target is invoked from the event loop context each time [`post()`](#post) is called. |
|  | [`Synchronizer`](#synchronizer-3) `inline` `explicit` | Creates and immediately starts a synchronizer with a variadic callback. |
|  | [`~Synchronizer`](#synchronizer-4) `virtual` | Destructor. |
| `void` | [`post`](#post)  | Send a synchronization request to the event loop. Call this each time you want the target method called synchronously. The synchronous method will be called on next iteration. This is not atomic, so do not expect a callback for every request. |
| `void` | [`start`](#start-5) `inline` | Starts the synchronizer with a variadic callback function. The callback is invoked from the event loop each time [`post()`](#post) is called. Throws `std::logic_error` if already running or if the handle is null. |
| `void` | [`start`](#start-6) `virtual` `override` | Starts the synchronizer with a `std::function` callback. Overrides [`Runner::start`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#start-3); delegates to the variadic `start` template. |
| `void` | [`cancel`](#cancel-3) `virtual` | Cancels the synchronizer, signalling the associated callback to stop. A subsequent [`post()`](#post) is needed to wake up the event loop so it can process the cancellation. |
| `void` | [`close`](#close-6) `virtual` | Cancels the synchronizer and closes the underlying `uv_async_t` handle. Safe to call multiple times; no-op if already closed. |
| [`uv::Handle`](https://auscaster.com/icey/docs/api-reference/icy-uv-Handle.md#handle-6)< uv_async_t > & | [`handle`](#handle-2)  | Returns a reference to the underlying libuv async handle. |

---

<a id="synchronizer-1"></a>

### Synchronizer

```cpp
Synchronizer(uv::Loop * loop)
```

[Defined in src/base/include/icy/synchronizer.h:47](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L47)

Creates a synchronizer attached to the given event loop without a callback. Call [`start()`](#start-5) separately to register the callback before using [`post()`](#post).

#### Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `loop` | [`uv::Loop`](https://auscaster.com/icey/docs/api-reference/uv.md#loop-1) * | Event loop to attach the async handle to. |

---

<a id="synchronizer-2"></a>

### Synchronizer

```cpp
Synchronizer(std::function< void()> target, uv::Loop * loop = uv::defaultLoop())
```

[Defined in src/base/include/icy/synchronizer.h:53](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L53)

Creates and immediately starts a synchronizer with a single callback function. The target is invoked from the event loop context each time [`post()`](#post) is called.

#### Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `target` | `std::function< void()>` | Callback to invoke on each event loop wakeup. |
| `loop` | [`uv::Loop`](https://auscaster.com/icey/docs/api-reference/uv.md#loop-1) * | Event loop to attach the async handle to. |

---

<a id="synchronizer-3"></a>

### Synchronizer

`inline` `explicit`

```cpp
template<typename Function, typename... Args> inline explicit Synchronizer(Function && func, Args &&... args, uv::Loop * loop = uv::defaultLoop())
```

[Defined in src/base/include/icy/synchronizer.h:62](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L62)

Creates and immediately starts a synchronizer with a variadic callback.

#### Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `func` | `Function &&` | Callable to invoke on each event loop wakeup. |
| `args` | `Args &&...` | Arguments forwarded to `func`. |
| `loop` | [`uv::Loop`](https://auscaster.com/icey/docs/api-reference/uv.md#loop-1) * | Event loop to attach the async handle to. |

---

<a id="synchronizer-4"></a>

### ~Synchronizer

`virtual`

```cpp
virtual ~Synchronizer()
```

[Defined in src/base/include/icy/synchronizer.h:70](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L70)

Destructor.

---

<a id="post"></a>

### post

```cpp
void post()
```

[Defined in src/base/include/icy/synchronizer.h:76](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L76)

Send a synchronization request to the event loop. Call this each time you want the target method called synchronously. The synchronous method will be called on next iteration. This is not atomic, so do not expect a callback for every request.

---

<a id="start-5"></a>

### start

`inline`

```cpp
template<typename Function, typename... Args> inline void start(Function && func, Args &&... args)
```

[Defined in src/base/include/icy/synchronizer.h:86](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L86)

Starts the synchronizer with a variadic callback function. The callback is invoked from the event loop each time [`post()`](#post) is called. Throws `std::logic_error` if already running or if the handle is null.

#### Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `func` | `Function &&` | Callable to invoke on each event loop wakeup. |
| `args` | `Args &&...` | Arguments forwarded to `func`. |

---

<a id="start-6"></a>

### start

`virtual` `override`

```cpp
virtual void start(std::function< void()> func) override
```

[Defined in src/base/include/icy/synchronizer.h:132](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L132)

Starts the synchronizer with a `std::function` callback. Overrides [`Runner::start`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#start-3); delegates to the variadic `start` template.

#### Reimplements

- [`Runner::start`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#start-3)

#### Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `func` | `std::function< void()>` | Callback invoked from the event loop on each [`post()`](#post) call. |

---

<a id="cancel-3"></a>

### cancel

`virtual`

```cpp
virtual void cancel()
```

[Defined in src/base/include/icy/synchronizer.h:136](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L136)

Cancels the synchronizer, signalling the associated callback to stop. A subsequent [`post()`](#post) is needed to wake up the event loop so it can process the cancellation.

---

<a id="close-6"></a>

### close

`virtual`

```cpp
virtual void close()
```

[Defined in src/base/include/icy/synchronizer.h:140](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L140)

Cancels the synchronizer and closes the underlying `uv_async_t` handle. Safe to call multiple times; no-op if already closed.

---

<a id="handle-2"></a>

### handle

```cpp
uv::Handle< uv_async_t > & handle()
```

[Defined in src/base/include/icy/synchronizer.h:144](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L144)

Returns a reference to the underlying libuv async handle. 
#### Returns
Reference to the `uv::Handle<uv_async_t>`.

## Protected Attributes

| Return | Name | Description |
|--------|------|-------------|
| [`uv::Handle`](https://auscaster.com/icey/docs/api-reference/icy-uv-Handle.md#handle-6)< uv_async_t > | [`_handle`](#_handle-2)  |  |
| `std::mutex` | [`_postMutex`](#_postmutex)  | Serializes [`post()`](#post) (any thread) against [`close()`](#close-6). The handle context uses a non-atomic intrusive refcount owned by the loop thread, so [`post()`](#post) must never copy the context pointer; it reads the raw handle under this mutex instead. |

---

<a id="_handle-2"></a>

### _handle

```cpp
uv::Handle< uv_async_t > _handle
```

Type: [`uv::Handle`](https://auscaster.com/icey/docs/api-reference/icy-uv-Handle.md#handle-6)< uv_async_t >

[Defined in src/base/include/icy/synchronizer.h:149](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L149)

---

<a id="_postmutex"></a>

### _postMutex

```cpp
std::mutex _postMutex
```

[Defined in src/base/include/icy/synchronizer.h:155](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L155)

Serializes [`post()`](#post) (any thread) against [`close()`](#close-6). The handle context uses a non-atomic intrusive refcount owned by the loop thread, so [`post()`](#post) must never copy the context pointer; it reads the raw handle under this mutex instead.

## Protected Methods

| Return | Name | Description |
|--------|------|-------------|
| `bool` | [`async`](#async-2) `virtual` `const` `override` | Returns true if the implementation is thread-based. |

---

<a id="async-2"></a>

### async

`virtual` `const` `override`

```cpp
virtual bool async() const override
```

[Defined in src/base/include/icy/synchronizer.h:147](https://github.com/auscaster/icey/blob/main/src/base/include/icy/synchronizer.h#L147)

Returns true if the implementation is thread-based. 
#### Returns
True for thread-backed runners, false for event-loop-driven runners.

#### Reimplements

- [`Runner::async`](https://auscaster.com/icey/docs/api-reference/icy-Runner.md#async-1)
