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.
Files changed (25) hide show
  1. {pytq_cxx-1.0.2/pytq_cxx.egg-info → pytq_cxx-1.1.0}/PKG-INFO +8 -3
  2. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/README_pytq.md +6 -1
  3. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/bind.cpp +33 -1
  4. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/thread_pool.h +4 -4
  5. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/timer_queue.h +9 -8
  6. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/utils/sched_utils.h +25 -2
  7. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/version.h +1 -1
  8. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/pyproject.toml +1 -1
  9. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/pytq/__init__.py +2 -2
  10. pytq_cxx-1.1.0/pytq/pythonize.py +20 -0
  11. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0/pytq_cxx.egg-info}/PKG-INFO +8 -3
  12. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/pytq_cxx.egg-info/SOURCES.txt +1 -1
  13. pytq_cxx-1.0.2/pytq/awaitable_future.py +0 -19
  14. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/MANIFEST.in +0 -0
  15. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/internal/concepts.h +0 -0
  16. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/internal/log4cxx_proxy.h +0 -0
  17. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/internal/promise_utils.h +0 -0
  18. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/include/yatq/utils/logging_utils.h +0 -0
  19. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/_yatq/traits.h +0 -0
  20. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/pytq_cxx.egg-info/dependency_links.txt +0 -0
  21. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/pytq_cxx.egg-info/top_level.txt +0 -0
  22. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/setup.cfg +0 -0
  23. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/setup.py +0 -0
  24. {pytq_cxx-1.0.2 → pytq_cxx-1.1.0}/setup_helpers/find_dep_headers.cmake +0 -0
  25. {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
1
+ Metadata-Version: 2.4
2
2
  Name: pytq-cxx
3
- Version: 1.0.2
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, AwaitableFuture
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, AwaitableFuture
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 #" + std::to_string(i);
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(const std::string& thread_tag) {
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=" + std::to_string(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=" + std::to_string(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, "Cleared " + std::to_string(total_jobs) + " timers and " + std::to_string(canceled_timers) + " canceled timers");
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=" + std::to_string(heap_entry.uid) + " has been canceled");
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, "Purged " + std::to_string(canceled_timers) + " canceled timers");
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=" + std::to_string(current_uid) + " has been canceled");
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=" + std::to_string(current_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 " + utils::time_point_to_string(deadline));
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(logger, "Set sched params thread=" + thread_tag + " policy=" + sched_policy_to_string(sched_policy) + " priority=" + std::to_string(priority));
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=" + thread_tag + ": " + std::string(std::strerror(errno)));
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) {
@@ -1,6 +1,6 @@
1
1
  #ifndef _YATQ_VERSION_H
2
2
  #define _YATQ_VERSION_H
3
3
 
4
- #define YATQ_VERSION "1.0.2"
4
+ #define YATQ_VERSION "1.1.0"
5
5
 
6
6
  #endif
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pytq-cxx"
7
- version = "1.0.2"
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 .awaitable_future import AwaitableFuture
2
+ from .pythonize import pythonize
3
3
 
4
4
 
5
- __all__ = ['__version__', 'TimerQueue', 'TimerHandle', 'ThreadPool', 'utils', 'AwaitableFuture']
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
1
+ Metadata-Version: 2.4
2
2
  Name: pytq-cxx
3
- Version: 1.0.2
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, AwaitableFuture
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/awaitable_future.py
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