ANTICHAT

ANTICHAT (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   ktsignal - библиотека для сигналов (https://forum.antichat.xyz/showthread.php?t=1400620)

kin4stat 03.09.2021 19:52

ktsignal​Небольшая библиотека сигналов для C++. Для компиляции потребуется C++17 (на MSVC можно скомпилировать на C++14)

Немного примеров кода​Базовое использование:​Пример ниже показывает базовое использование сигналов

C++:





Код:

void
on_click
(
int
value
)
{
}
class
A
{
public
:
void
on_class_click
(
int
value
)
{
}
}
;
int
main
(
)
{
// Сигнал с сигнатурой функции в шаблонном параметре
ktsignal
::
ktsignal

click
{
}
;
// Подключение обычной функции
click
.
connect
(
on_click
)
;
// Подключение member function
A object
;
click
.
connect
(
&
object
,
&
A
::
on_class_click
)
;
// Подключение лямбда функции
click
.
connect
(
[
]
(
int
)
{
}
)
;
// Вызов коллбэков
click
.
emit
(
1
)
;
}



Scoped соединения автоматически отключаются в конце области видимости

C++:





[CODE]
void
on_click
(
int
value
)
{
}
class
A
{
public
:
void
on_class_click
(
int
value
)
{
}
}
;
int
main
(
)
{
ktsignal
::
ktsignal

click
{
}
;
{
auto
connection
=
click
.
scoped_connect
(
on_click
)
;
A object
;
auto
method_connection
=
click
.
scoped_connect
(
&
object
,
&
A
::
on_class_click
)
;
click
.
scoped_connect
(
[
]
(
int
v
)
{
std
::
cout



Подключение / Отключение коллбэков​

C++:





Код:

auto
connection
=
click
.
connect
(
on_click
)
;
// Подключение лямбда функции
click
.
connect
(
[
]
(
int
)
{
}
)
;
// Вызов сигнала (on_click и lambda будут вызваны)
click
.
emit
(
1
)
;
// Отключение on_click коллбэка от сигнала
connection
.
disconnect
(
)
;
// Только лямбда будет вызвана
click
.
emit
(
1
)
;



Несколько важных замечаний об объекте
Код:

ktsignal_connection
  • Код:

    ktsignal_connection
    можно создавать по умолчанию, перемещать, но не копировать.
  • Вы должны убедиться, что соединение не будет использоваться после уничтожения сигнала.
Итерация через слоты сигнала​Вы можете итерироваться по сигналу через range-based for при этом получая значение возврата

C++:





[CODE]
int
on_click
(
int
value
)
{
return
5
;
}
int
on_click_second
(
int
value
)
{
return
1
;
}
int
main
(
)
{
ktsignal
::
ktsignal

click
{
}
;
click
.
connect
(
on_click
)
;
click
.
connect
(
on_click_second
)
;
// Будет выведено `emit_iterate returned 5 emit_iterate returned 1`
for
(
auto
returned
:
signal
.
emit_iterate
(
1
)
)
{
std
::
cout



Также вы легко можете использовать функции из стандартной библиотеки C++

C++:





[CODE]
int
on_click
(
int
value
)
{
return
5
;
}
int
on_click_second
(
int
value
)
{
return
1
;
}
int
main
(
)
{
ktsignal
::
ktsignal

click
{
}
;
click
.
connect
(
on_click
)
;
click
.
connect
(
on_click_second
)
;
auto
iterate
=
signal
.
emit_iterate
(
0
)
;
auto
accumulated
=
std
::
accumulate
(
iterate
.
begin
(
)
,
iterate
.
end
(
)
,
0
)
;
// Will display 6
std
::
cout



Использование ktsignal в многопоточном коде​Для многопоточного кода вы должны использовать
Код:

ktsignal_threadsafe
C++:





Код:

void
func_thread
(
int
v
)
{
std
::
cout

signal
{
}
;
signal
.
connect
(
func_thread
)
;
// Создание потока который сразу же вызовет emit
std
::
thread
(
[
&
signal
]
(
)
{
// Создание потока который вызовет emit спустя 100мс
std
::
thread
(
[
&
signal
]
(
)
{
std
::
this_thread
::
sleep_for
(
100
ms
)
;
signal
.
emit
(
1
)
;
}
)
.
detach
(
)
;
signal
.
emit
(
2
)
;
}
)
.
join
(
)
;
std
::
this_thread
::
sleep_for
(
1.5
s
)
;
}



Код:





Код:

Вывод:
[func_thread] - before sleep
[func_thread] - before sleep
[func_thread] - after sleep
[func_thread] - after sleep



C++:





Код:

void
func_thread
(
int
v
)
{
std
::
cout

signal
{
}
;
signal
.
connect
(
func_thread
)
;
// Создание потока который сразу же вызовет emit
std
::
thread
(
[
&
signal
]
(
)
{
// Создание потока который вызовет emit спустя 100мс
std
::
thread
(
[
&
signal
]
(
)
{
std
::
this_thread
::
sleep_for
(
100
ms
)
;
signal
.
emit
(
1
)
;
}
)
.
detach
(
)
;
signal
.
emit
(
2
)
;
}
)
.
join
(
)
;
std
::
this_thread
::
sleep_for
(
1.5
s
)
;
}



Код:





Код:

Вывод:
[func_thread] - before sleep
[func_thread] - after sleep
[func_thread] - before sleep
[func_thread] - after sleep



Download & Source:

GitHub - KiN4StAt/ktsignal

Contribute to KiN4StAt/ktsignal development by creating an account on GitHub.

github.com



SR_team 03.09.2021 21:33

Цитата:

Сообщение от kin4stat

void func_thread(int v) { std::cout signal{}; signal.connect(func_thread); // Создание потока который сразу же вызовет emit std::thread([&signal]() { // Создание потока который вызовет emit спустя 100мс std::thread( [&signal]() { std::this_thread::sleep_for(100ms); signal.emit(1); } ).detach(); signal.emit(2); }).join(); std::this_thread::sleep_for(1.5s); }

как у тебя 1 и 2 в строку разворачивается? Где-то перегрузка опператора = или эти цифры что-то другое означают?

kin4stat 03.09.2021 21:34

Цитата:

Сообщение от SR_team

как у тебя 1 и 2 в строку разворачивается? Где-то перегрузка опператора = или эти цифры что-то другое означают?

Как ты лайкнул, я зашел в тему и увидел что проебался в примере.

Исправил до того как ты написал этот ответ.

SR_team 03.09.2021 21:38

Цитата:

Сообщение от kin4stat

Как ты лайкнул, я зашел в тему и увидел что проебался в примере.
Исправил до того как ты написал этот ответ.

Еще у тебя сигнатура позволяет возвращать что-то из сигналов. Как это работает? emit возвращает список результатов?

UPD: В примере многопоточки сигнал что-то возвращает int(int)

kin4stat 03.09.2021 21:40

Цитата:

Сообщение от SR_team

Еще у тебя сигнатура позволяет возвращать что-то из сигналов. Как это работает? emit возвращает список результатов?

emit_iterate позволяет по ним итерироваться(оператор * у итератора делает вызов слота в сигнале).

Не стал делать вектор возвратных значений для emit чтобы не оверхеда. При желании есть emit_iterate который позволяет это сделать

SR_team 03.09.2021 21:42

Цитата:

Сообщение от kin4stat

оператор * у итератора делает вызов слота в сигнале

Почему не оператор ()? Как это выглядит?

kin4stat 03.09.2021 22:14

Цитата:

Сообщение от SR_team

Почему не оператор ()? Как это выглядит?

Оператор * перегружен для вызова функции, чтобы в range-based for можно было красиво получить возвратное значение. Да и в целом это позволяет много красивых вещей делать.

Ну например вот такое:

C++:





Код:

auto
iterate
=
signal
.
emit_iterate
(
"test"
)
;
std
::
vector

vec
(
iterate
.
begin
(
)
,
iterate
.
end
(
)
)
;



И в vec будут все значения которые вернулись после вызова коллбэков

(Только что залил обновление на гите, теперь на MSVC можно конструировать STL контейнеры через итераторы. Microsoft решили выебнуться проверкой на поля итератора)

Цитата:

Сообщение от SR_team

Почему не оператор ()?

Мне кажется что вызов сигнала через () не очень явное действие, поэтому решил сделать на emit. В целом это на сам сигнал никак не влияет

Цитата:

Сообщение от SR_team

Как это выглядит?

Примерно вот так:

https://forum.antichat.xyz/attachments/27835703/

Цитата:

Сообщение от SR_team

UPD: В примере многопоточки сигнал что-то возвращает int(int)

UPD: сигнал может что-то возвращать, но при вызове через emit эти значения получить нельзя. Для этих целей стоит юзать emit_iterate и его методы begin и end возвращающие итераторы

vadimka0216 14.09.2021 15:46

qt на минималках

.deserve 18.09.2021 11:03

дежавю от документации

kin4stat 18.09.2021 12:11

Цитата:

Сообщение от .deserve

дежавю от документации

Делал по принципу буста, доку сам писал, хз


Время: 02:26