pytq-cxx 1.0.2__tar.gz → 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pytq_cxx-1.0.2/pytq_cxx.egg-info → pytq_cxx-1.1.0}/PKG-INFO +8 -3
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/README_pytq.md +6 -1
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/bind.cpp +33 -1
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/thread_pool.h +4 -4
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/timer_queue.h +9 -8
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/utils/sched_utils.h +25 -2
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/version.h +1 -1
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/pyproject.toml +1 -1
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/pytq/__init__.py +2 -2
- pytq_cxx-1.1.0/pytq/pythonize.py +20 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0/pytq_cxx.egg-info}/PKG-INFO +8 -3
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/pytq_cxx.egg-info/SOURCES.txt +1 -1
- pytq_cxx-1.0.2/pytq/awaitable_future.py +0 -19
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/MANIFEST.in +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/internal/concepts.h +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/internal/log4cxx_proxy.h +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/internal/promise_utils.h +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/utils/logging_utils.h +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/traits.h +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/pytq_cxx.egg-info/dependency_links.txt +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/pytq_cxx.egg-info/top_level.txt +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/setup.cfg +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/setup.py +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/setup_helpers/find_dep_headers.cmake +0 -0
- {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/setup_helpers/find_dep_libs.cmake +0 -0
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: pytq-cxx
|
3
|
-
Version: 1.0
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: single-threaded timer demultiplexer backed by C++ implementation
|
5
5
|
Author-email: Nikita Vaganov <nikita.e.vaganov@gmail.com>
|
6
6
|
Project-URL: Homepage, https://github.com/vaganov/yatq
|
@@ -18,4 +18,9 @@ see [yatq homepage](https://github.com/vaganov/yatq)
|
|
18
18
|
|
19
19
|
**NB:** Module name is, however, **pytq**
|
20
20
|
|
21
|
-
from pytq import ThreadPool, TimerQueue,
|
21
|
+
from pytq import ThreadPool, TimerQueue, pythonize
|
22
|
+
|
23
|
+
**NB:** On _macOS_ one may need to specify **MACOSX_DEPLOYMENT_TARGET** environment variable on install. Do not set
|
24
|
+
higher than the current _macOS_ version. Minimal supported version is **13.3**
|
25
|
+
|
26
|
+
(venv) $ MACOSX_DEPLOYMENT_TARGET=13.3 pip install pytq-cxx
|
@@ -6,4 +6,9 @@ see [yatq homepage](https://github.com/vaganov/yatq)
|
|
6
6
|
|
7
7
|
**NB:** Module name is, however, **pytq**
|
8
8
|
|
9
|
-
from pytq import ThreadPool, TimerQueue,
|
9
|
+
from pytq import ThreadPool, TimerQueue, pythonize
|
10
|
+
|
11
|
+
**NB:** On _macOS_ one may need to specify **MACOSX_DEPLOYMENT_TARGET** environment variable on install. Do not set
|
12
|
+
higher than the current _macOS_ version. Minimal supported version is **13.3**
|
13
|
+
|
14
|
+
(venv) $ MACOSX_DEPLOYMENT_TARGET=13.3 pip install pytq-cxx
|
@@ -3,6 +3,8 @@
|
|
3
3
|
#include <pybind11/chrono.h>
|
4
4
|
#include <pybind11/functional.h>
|
5
5
|
|
6
|
+
#include <functional>
|
7
|
+
|
6
8
|
#ifndef YATQ_DISABLE_FUTURES
|
7
9
|
#define BOOST_THREAD_PROVIDES_FUTURE
|
8
10
|
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION
|
@@ -18,7 +20,9 @@
|
|
18
20
|
namespace py = pybind11;
|
19
21
|
|
20
22
|
using result_type = py::object;
|
23
|
+
#ifndef YATQ_DISABLE_FUTURES
|
21
24
|
using Future = boost::future<result_type>;
|
25
|
+
#endif
|
22
26
|
using Executable = std::function<result_type(void)>;
|
23
27
|
using ThreadPool = yatq::ThreadPool<Executable>;
|
24
28
|
using TimerQueue = yatq::TimerQueue<ThreadPool>;
|
@@ -26,10 +30,38 @@ using TimerQueue = yatq::TimerQueue<ThreadPool>;
|
|
26
30
|
PYBIND11_MODULE(_yatq, m) {
|
27
31
|
#ifndef YATQ_DISABLE_FUTURES
|
28
32
|
auto boost_submodule = m.def_submodule("boost");
|
33
|
+
|
34
|
+
py::enum_<boost::launch>(boost_submodule, "launch")
|
35
|
+
.value("none", boost::launch::none)
|
36
|
+
.value("async_", boost::launch::async) // sic!
|
37
|
+
.value("deferred", boost::launch::deferred)
|
38
|
+
#ifdef BOOST_THREAD_PROVIDES_EXECUTORS
|
39
|
+
.value("executor", boost::launch::executor)
|
40
|
+
#endif
|
41
|
+
.value("inherit", boost::launch::inherit)
|
42
|
+
.value("sync", boost::launch::sync)
|
43
|
+
.value("any", boost::launch::any)
|
44
|
+
.export_values();
|
45
|
+
|
29
46
|
py::class_<Future>(boost_submodule, "future")
|
30
47
|
.def("get", &Future::get, py::call_guard<py::gil_scoped_release>())
|
31
48
|
.def("wait", &Future::wait, py::call_guard<py::gil_scoped_release>())
|
32
|
-
.def("is_ready", py::overload_cast<>(&Future::is_ready, py::const_))
|
49
|
+
.def("is_ready", py::overload_cast<>(&Future::is_ready, py::const_))
|
50
|
+
.def(
|
51
|
+
"then",
|
52
|
+
[] (Future& _this, std::function<result_type(Future&&)>&& func) {
|
53
|
+
return _this.then(std::move(func));
|
54
|
+
},
|
55
|
+
py::arg("func")
|
56
|
+
)
|
57
|
+
.def(
|
58
|
+
"then",
|
59
|
+
[] (Future& _this, boost::launch policy, std::function<result_type(Future&&)>&& func) {
|
60
|
+
return _this.then(policy, std::move(func));
|
61
|
+
},
|
62
|
+
py::arg("policy"),
|
63
|
+
py::arg("func")
|
64
|
+
);
|
33
65
|
#endif
|
34
66
|
|
35
67
|
#ifndef YATQ_DISABLE_PTHREAD
|
@@ -2,8 +2,8 @@
|
|
2
2
|
#define _YATQ_THREAD_POOL_H
|
3
3
|
|
4
4
|
#include <condition_variable>
|
5
|
-
#include <cstdlib>
|
6
5
|
#include <deque>
|
6
|
+
#include <format>
|
7
7
|
#include <functional>
|
8
8
|
#include <mutex>
|
9
9
|
#include <string>
|
@@ -65,8 +65,8 @@ public:
|
|
65
65
|
if (!_running) {
|
66
66
|
_running = true;
|
67
67
|
for (int i = 0; i < num_threads; ++i) {
|
68
|
-
std::string thread_tag = "pool thread #"
|
69
|
-
auto thread = std::thread(&ThreadPool::thread_routine, this, thread_tag);
|
68
|
+
std::string thread_tag = std::format("pool thread #{}", i);
|
69
|
+
auto thread = std::thread(&ThreadPool::thread_routine, this, std::move(thread_tag));
|
70
70
|
_pool.push_back(std::move(thread));
|
71
71
|
}
|
72
72
|
}
|
@@ -119,7 +119,7 @@ public:
|
|
119
119
|
}
|
120
120
|
|
121
121
|
private:
|
122
|
-
void thread_routine(
|
122
|
+
void thread_routine(std::string&& thread_tag) {
|
123
123
|
#ifndef YATQ_DISABLE_LOGGING
|
124
124
|
static auto logger = log4cxx::Logger::getLogger("yatq.thread_pool");
|
125
125
|
#endif
|
@@ -4,6 +4,7 @@
|
|
4
4
|
#include <algorithm>
|
5
5
|
#include <chrono>
|
6
6
|
#include <condition_variable>
|
7
|
+
#include <format>
|
7
8
|
#include <mutex>
|
8
9
|
#include <thread>
|
9
10
|
#include <unordered_map>
|
@@ -171,7 +172,7 @@ public:
|
|
171
172
|
if (is_first) {
|
172
173
|
_cond.notify_one();
|
173
174
|
}
|
174
|
-
LOG4CXX_DEBUG(logger, "New timer uid="
|
175
|
+
LOG4CXX_DEBUG(logger, std::format("New timer uid={}", uid));
|
175
176
|
return {
|
176
177
|
uid
|
177
178
|
, deadline
|
@@ -197,7 +198,7 @@ public:
|
|
197
198
|
std::lock_guard<std::mutex> guard(_lock);
|
198
199
|
auto i = _jobs.find(uid);
|
199
200
|
if (i != _jobs.end()) {
|
200
|
-
LOG4CXX_DEBUG(logger, "Canceling timer uid="
|
201
|
+
LOG4CXX_DEBUG(logger, std::format("Canceling timer uid={}", uid));
|
201
202
|
_jobs.erase(i);
|
202
203
|
was_removed = true;
|
203
204
|
was_first = (_heap[0].uid == uid);
|
@@ -233,7 +234,7 @@ public:
|
|
233
234
|
_cond.notify_one();
|
234
235
|
}
|
235
236
|
auto canceled_timers = total_timers - total_jobs;
|
236
|
-
LOG4CXX_DEBUG(logger,
|
237
|
+
LOG4CXX_DEBUG(logger, std::format("Cleared {} timers and {} canceled timers", total_jobs, canceled_timers));
|
237
238
|
}
|
238
239
|
|
239
240
|
/**
|
@@ -258,7 +259,7 @@ public:
|
|
258
259
|
*i++ = std::move(heap_entry);
|
259
260
|
}
|
260
261
|
else {
|
261
|
-
LOG4CXX_DEBUG(logger, "Timer uid=
|
262
|
+
LOG4CXX_DEBUG(logger, std::format("Timer uid={} has been canceled", heap_entry.uid));
|
262
263
|
}
|
263
264
|
}
|
264
265
|
std::make_heap(heap.begin(), heap.end(), TimerQueue::heap_cmp);
|
@@ -266,7 +267,7 @@ public:
|
|
266
267
|
}
|
267
268
|
}
|
268
269
|
// NB: 'demux()' never waits on a canceled timer => no need to notify
|
269
|
-
LOG4CXX_DEBUG(logger,
|
270
|
+
LOG4CXX_DEBUG(logger, std::format("Purged {} canceled timers", canceled_timers));
|
270
271
|
}
|
271
272
|
|
272
273
|
/**
|
@@ -298,7 +299,7 @@ private:
|
|
298
299
|
auto current_uid = _heap[0].uid;
|
299
300
|
auto i = _jobs.find(current_uid);
|
300
301
|
if (i == _jobs.end()) {
|
301
|
-
LOG4CXX_DEBUG(logger, "Timer uid=
|
302
|
+
LOG4CXX_DEBUG(logger, std::format("Timer uid={} has been canceled", current_uid));
|
302
303
|
std::pop_heap(_heap.begin(), _heap.end(), TimerQueue::heap_cmp);
|
303
304
|
_heap.pop_back();
|
304
305
|
deadline_expired = false;
|
@@ -309,7 +310,7 @@ private:
|
|
309
310
|
deadline_expired = (_heap[0].deadline <= now);
|
310
311
|
}
|
311
312
|
if (deadline_expired) {
|
312
|
-
LOG4CXX_DEBUG(logger, "Executing timer uid="
|
313
|
+
LOG4CXX_DEBUG(logger, std::format("Executing timer uid={}", current_uid));
|
313
314
|
auto node = _jobs.extract(i);
|
314
315
|
std::pop_heap(_heap.begin(), _heap.end(), TimerQueue::heap_cmp);
|
315
316
|
_heap.pop_back();
|
@@ -336,7 +337,7 @@ private:
|
|
336
337
|
// NB: without this explicit cast duration type may be deduced incorrectly
|
337
338
|
// on Linux this leads to waiting for a random time point
|
338
339
|
std::chrono::time_point<Clock, typename Clock::duration> deadline = _heap[0].deadline;
|
339
|
-
LOG4CXX_TRACE(logger, "Wait until "
|
340
|
+
LOG4CXX_TRACE(logger, std::format("Wait until {}", utils::time_point_to_string(deadline)));
|
340
341
|
bool notified = _cond.wait_until(
|
341
342
|
guard,
|
342
343
|
deadline,
|
@@ -2,6 +2,7 @@
|
|
2
2
|
#define _YATQ_UTILS_SCHED_UTILS_H
|
3
3
|
|
4
4
|
#include <cerrno>
|
5
|
+
#include <format>
|
5
6
|
#include <string>
|
6
7
|
|
7
8
|
#include <pthread.h>
|
@@ -13,6 +14,14 @@ namespace yatq::utils {
|
|
13
14
|
|
14
15
|
typedef enum {min_priority = 0, max_priority = -1} priority_t;
|
15
16
|
|
17
|
+
/**
|
18
|
+
* set scheduling parameters for a thread
|
19
|
+
* @param handle thread handle
|
20
|
+
* @param sched_policy \a SCHED_OTHER | \a SCHED_RR | \a SCHED_FIFO
|
21
|
+
* @param priority explicit priority
|
22
|
+
* @param thread_tag thread tag (used for logging purposes only)
|
23
|
+
* @return \a true if scheduling parameters have been set and \a false otherwise
|
24
|
+
*/
|
16
25
|
inline bool set_sched_params(pthread_t handle, int sched_policy, int priority, const std::string& thread_tag = "unspecified") {
|
17
26
|
#ifndef YATQ_DISABLE_LOGGING
|
18
27
|
static auto logger = log4cxx::Logger::getLogger("yatq.utils.sched");
|
@@ -23,15 +32,29 @@ inline bool set_sched_params(pthread_t handle, int sched_policy, int priority, c
|
|
23
32
|
pthread_getschedparam(handle, &prev_sched_policy, &sched);
|
24
33
|
sched.sched_priority = priority;
|
25
34
|
if (pthread_setschedparam(handle, sched_policy, &sched) == 0) {
|
26
|
-
LOG4CXX_INFO(
|
35
|
+
LOG4CXX_INFO(
|
36
|
+
logger,
|
37
|
+
std::format(
|
38
|
+
"Set sched params thread='{}' policy={} priority={}",
|
39
|
+
thread_tag, sched_policy_to_string(sched_policy), priority
|
40
|
+
)
|
41
|
+
);
|
27
42
|
return true;
|
28
43
|
}
|
29
44
|
else {
|
30
|
-
LOG4CXX_WARN(logger, "Failed to set sched params thread=
|
45
|
+
LOG4CXX_WARN(logger, std::format("Failed to set sched params thread='{}': {}", thread_tag, std::strerror(errno)));
|
31
46
|
return false;
|
32
47
|
}
|
33
48
|
}
|
34
49
|
|
50
|
+
/**
|
51
|
+
* set scheduling parameters for a thread
|
52
|
+
* @param handle thread handle
|
53
|
+
* @param sched_policy \a SCHED_OTHER | \a SCHED_RR | \a SCHED_FIFO
|
54
|
+
* @param priority_tag \a yatq::utils::max_priority | \a yatq::utils::min_priority
|
55
|
+
* @param thread_tag thread tag (used for logging purposes only)
|
56
|
+
* @return \a true if scheduling parameters have been set and \a false otherwise
|
57
|
+
*/
|
35
58
|
inline bool set_sched_params(pthread_t handle, int sched_policy, priority_t priority_tag, const std::string& thread_tag = "unspecified") {
|
36
59
|
int priority;
|
37
60
|
switch (priority_tag) {
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "pytq-cxx"
|
7
|
-
version = "1.0
|
7
|
+
version = "1.1.0"
|
8
8
|
authors = [{name="Nikita Vaganov", email="nikita.e.vaganov@gmail.com"}]
|
9
9
|
description = "single-threaded timer demultiplexer backed by C++ implementation"
|
10
10
|
readme = "README_pytq.md"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from _yatq import __version__, TimerQueue, TimerHandle, ThreadPool, utils
|
2
|
-
from .
|
2
|
+
from .pythonize import pythonize
|
3
3
|
|
4
4
|
|
5
|
-
__all__ = ['__version__', 'TimerQueue', 'TimerHandle', 'ThreadPool', 'utils', '
|
5
|
+
__all__ = ['__version__', 'TimerQueue', 'TimerHandle', 'ThreadPool', 'utils', 'pythonize']
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import asyncio
|
2
|
+
from typing import Any
|
3
|
+
|
4
|
+
import _yatq.boost
|
5
|
+
|
6
|
+
|
7
|
+
__all__ = ['pythonize']
|
8
|
+
|
9
|
+
|
10
|
+
def pythonize(src: _yatq.boost.future) -> asyncio.Future[Any]:
|
11
|
+
chained = asyncio.Future()
|
12
|
+
|
13
|
+
def on_done(future: _yatq.boost.future):
|
14
|
+
try:
|
15
|
+
chained.get_loop().call_soon_threadsafe(chained.set_result, future.get())
|
16
|
+
except Exception as exc:
|
17
|
+
chained.set_exception(exc)
|
18
|
+
|
19
|
+
src.then(func=on_done, policy=_yatq.boost.launch.sync)
|
20
|
+
return chained
|
@@ -1,6 +1,6 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: pytq-cxx
|
3
|
-
Version: 1.0
|
3
|
+
Version: 1.1.0
|
4
4
|
Summary: single-threaded timer demultiplexer backed by C++ implementation
|
5
5
|
Author-email: Nikita Vaganov <nikita.e.vaganov@gmail.com>
|
6
6
|
Project-URL: Homepage, https://github.com/vaganov/yatq
|
@@ -18,4 +18,9 @@ see [yatq homepage](https://github.com/vaganov/yatq)
|
|
18
18
|
|
19
19
|
**NB:** Module name is, however, **pytq**
|
20
20
|
|
21
|
-
from pytq import ThreadPool, TimerQueue,
|
21
|
+
from pytq import ThreadPool, TimerQueue, pythonize
|
22
|
+
|
23
|
+
**NB:** On _macOS_ one may need to specify **MACOSX_DEPLOYMENT_TARGET** environment variable on install. Do not set
|
24
|
+
higher than the current _macOS_ version. Minimal supported version is **13.3**
|
25
|
+
|
26
|
+
(venv) $ MACOSX_DEPLOYMENT_TARGET=13.3 pip install pytq-cxx
|
@@ -13,7 +13,7 @@ _yatq/include/yatq/internal/promise_utils.h
|
|
13
13
|
_yatq/include/yatq/utils/logging_utils.h
|
14
14
|
_yatq/include/yatq/utils/sched_utils.h
|
15
15
|
pytq/__init__.py
|
16
|
-
pytq/
|
16
|
+
pytq/pythonize.py
|
17
17
|
pytq_cxx.egg-info/PKG-INFO
|
18
18
|
pytq_cxx.egg-info/SOURCES.txt
|
19
19
|
pytq_cxx.egg-info/dependency_links.txt
|
@@ -1,19 +0,0 @@
|
|
1
|
-
import asyncio
|
2
|
-
|
3
|
-
|
4
|
-
__all__ = ['AwaitableFuture']
|
5
|
-
|
6
|
-
|
7
|
-
class AwaitableFuture:
|
8
|
-
def __init__(self, future):
|
9
|
-
self._future = future
|
10
|
-
|
11
|
-
def __await__(self):
|
12
|
-
while not self._future.is_ready():
|
13
|
-
yield
|
14
|
-
return self._future.get() # NB: return, not yield
|
15
|
-
|
16
|
-
async def get(self):
|
17
|
-
while not self._future.is_ready():
|
18
|
-
await asyncio.sleep(0)
|
19
|
-
return self._future.get()
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|