aboutsummaryrefslogtreecommitdiff
path: root/ouroboros/_timespec.py
diff options
context:
space:
mode:
Diffstat (limited to 'ouroboros/_timespec.py')
-rw-r--r--ouroboros/_timespec.py64
1 files changed, 64 insertions, 0 deletions
diff --git a/ouroboros/_timespec.py b/ouroboros/_timespec.py
new file mode 100644
index 0000000..2fcf666
--- /dev/null
+++ b/ouroboros/_timespec.py
@@ -0,0 +1,64 @@
+#
+# Ouroboros - Copyright (C) 2016 - 2026
+#
+# Internal helpers for translating float seconds <-> struct timespec.
+#
+# Dimitri Staessens <dimitri@ouroboros.rocks>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# version 2.1 as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., http://www.fsf.org/about/contact/.
+#
+
+"""Shared float-seconds <-> ``struct timespec *`` conversions.
+
+The dev and event modules both deal in seconds-as-float timeouts on
+the Python side and pass ``struct timespec *`` to the C library.
+The helpers take the caller's ``ffi`` instance as a parameter so the
+returned CData is bound to the right CFFI module.
+"""
+
+from __future__ import annotations
+
+from math import modf
+from typing import Optional
+
+BILLION = 1000 * 1000 * 1000
+
+
+def fl_to_timespec(ffi, timeo: Optional[float]):
+ """Convert *timeo* (seconds, or None) to a ``struct timespec *``.
+
+ *None* yields ``ffi.NULL`` (block forever). A non-positive *timeo*
+ yields a zeroed timespec (async / poll).
+ """
+ if timeo is None:
+ return ffi.NULL
+ if timeo <= 0:
+ return ffi.new("struct timespec *", [0, 0])
+ frac, whole = modf(timeo)
+ _timeo = ffi.new("struct timespec *")
+ _timeo.tv_sec = int(whole)
+ _timeo.tv_nsec = int(frac * BILLION)
+ return _timeo
+
+
+def timespec_to_fl(ffi, _timeo) -> Optional[float]:
+ """Convert a ``struct timespec *`` to seconds-as-float.
+
+ ``ffi.NULL`` yields *None* (block forever).
+ """
+ if _timeo == ffi.NULL:
+ return None
+ if _timeo.tv_sec <= 0 and _timeo.tv_nsec == 0:
+ return 0.0
+ return _timeo.tv_sec + _timeo.tv_nsec / BILLION