diff --git a/Cargo.lock b/Cargo.lock index 4cc660526..303880c47 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,6 +55,21 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.75" @@ -373,6 +388,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-targets 0.52.4", +] + [[package]] name = "cipher" version = "0.4.4" @@ -911,6 +940,29 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" version = "0.4.0" @@ -2636,13 +2688,22 @@ dependencies = [ "windows_x86_64_msvc 0.34.0", ] +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.4", +] + [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -2660,12 +2721,33 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + [[package]] name = "windows_aarch64_msvc" version = "0.34.0" @@ -2678,6 +2760,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + [[package]] name = "windows_i686_gnu" version = "0.34.0" @@ -2690,6 +2778,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + [[package]] name = "windows_i686_msvc" version = "0.34.0" @@ -2702,6 +2796,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + [[package]] name = "windows_x86_64_gnu" version = "0.34.0" @@ -2714,12 +2814,24 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + [[package]] name = "windows_x86_64_msvc" version = "0.34.0" @@ -2732,6 +2844,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + [[package]] name = "zenoh" version = "0.11.0-dev" @@ -2796,10 +2914,12 @@ dependencies = [ "async-std", "async-trait", "cbindgen", + "chrono", "env_logger", "fs2", "futures", "json5", + "lazy_static", "libc", "log", "rand", diff --git a/Cargo.toml b/Cargo.toml index 52deaa71c..95867f95f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,9 +41,11 @@ maintenance = { status = "actively-developed" } [dependencies] async-std = "=1.12.0" async-trait = "0.1.66" +chrono = "0.4.34" env_logger = "0.10.0" futures = "0.3.26" json5 = "0.4.1" +lazy_static = "1.4.0" libc = "0.2.139" log = "0.4.17" rand = "0.8.5" diff --git a/Cargo.toml.in b/Cargo.toml.in index d1eec11bd..f434df3a1 100644 --- a/Cargo.toml.in +++ b/Cargo.toml.in @@ -41,9 +41,11 @@ maintenance = { status = "actively-developed" } [dependencies] async-std = "=1.12.0" async-trait = "0.1.66" +chrono = "0.4.34" env_logger = "0.10.0" futures = "0.3.26" json5 = "0.4.1" +lazy_static = "1.4.0" libc = "0.2.139" log = "0.4.17" rand = "0.8.5" diff --git a/examples/z_liveliness.c b/examples/z_liveliness.c index b21cc40bc..4191b0496 100644 --- a/examples/z_liveliness.c +++ b/examples/z_liveliness.c @@ -13,12 +13,6 @@ #include #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" int main(int argc, char **argv) { @@ -63,7 +57,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } else if (c == 'd') { printf("Undeclaring liveliness token...\n"); z_drop(z_move(token)); diff --git a/examples/z_ping.c b/examples/z_ping.c index bb061baee..fdc08f71d 100644 --- a/examples/z_ping.c +++ b/examples/z_ping.c @@ -2,7 +2,6 @@ #include #include #include -#include #include "zenoh.h" @@ -58,35 +57,27 @@ int main(int argc, char** argv) { z_mutex_lock(&mutex); if (args.warmup_ms) { printf("Warming up for %dms...\n", args.warmup_ms); - struct timespec wmup_start, wmup_stop, wmup_timeout; - clock_gettime(CLOCK_MONOTONIC, &wmup_start); + z_clock_t warmup_start = z_clock_now(); + unsigned long elapsed_us = 0; while (elapsed_us < args.warmup_ms * 1000) { - clock_gettime(CLOCK_REALTIME, &wmup_timeout); - wmup_timeout.tv_sec += PING_TIMEOUT_SEC; z_publisher_put(z_loan(pub), data, args.size, NULL); int s = z_condvar_wait(&cond, &mutex); if (s != 0) { handle_error_en(s, "z_condvar_wait"); } - clock_gettime(CLOCK_MONOTONIC, &wmup_stop); - elapsed_us = - (1000000 * (wmup_stop.tv_sec - wmup_start.tv_sec) + (wmup_stop.tv_nsec - wmup_start.tv_nsec) / 1000); + elapsed_us = z_clock_elapsed_us(&warmup_start); } } - struct timespec t_start, t_stop, t_timeout; unsigned long* results = z_malloc(sizeof(unsigned long) * args.number_of_pings); for (int i = 0; i < args.number_of_pings; i++) { - clock_gettime(CLOCK_REALTIME, &t_timeout); - t_timeout.tv_sec += PING_TIMEOUT_SEC; - clock_gettime(CLOCK_MONOTONIC, &t_start); + z_clock_t measure_start = z_clock_now(); z_publisher_put(z_loan(pub), data, args.size, NULL); int s = z_condvar_wait(&cond, &mutex); if (s != 0) { handle_error_en(s, "z_condvar_wait"); } - clock_gettime(CLOCK_MONOTONIC, &t_stop); - results[i] = (1000000 * (t_stop.tv_sec - t_start.tv_sec) + (t_stop.tv_nsec - t_start.tv_nsec) / 1000); + results[i] = z_clock_elapsed_us(&measure_start); } for (int i = 0; i < args.number_of_pings; i++) { printf("%d bytes: seq=%d rtt=%luµs, lat=%luµs\n", args.size, i, results[i], results[i] / 2); diff --git a/examples/z_pub.c b/examples/z_pub.c index 73fd02287..543cba694 100644 --- a/examples/z_pub.c +++ b/examples/z_pub.c @@ -15,12 +15,6 @@ #include #include "zenoh.h" -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif void matching_status_handler(const zcu_matching_status_t *matching_status, void *arg) { if (matching_status->matching) { @@ -72,7 +66,7 @@ int main(int argc, char **argv) { char buf[256]; for (int idx = 0; 1; ++idx) { - sleep(1); + z_sleep_s(1); sprintf(buf, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); z_publisher_put_options_t options = z_publisher_put_options_default(); diff --git a/examples/z_pub_attachment.c b/examples/z_pub_attachment.c index b75f245c3..a24133e91 100644 --- a/examples/z_pub_attachment.c +++ b/examples/z_pub_attachment.c @@ -15,12 +15,6 @@ #include #include "zenoh.h" -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif int main(int argc, char **argv) { char *keyexpr = "demo/example/zenoh-c-pub"; @@ -69,7 +63,7 @@ int main(int argc, char **argv) { char buf[256]; char buf_ind[16]; for (int idx = 0; 1; ++idx) { - sleep(1); + z_sleep_s(1); // add some other attachment value sprintf(buf_ind, "%d", idx); diff --git a/examples/z_pub_cache.c b/examples/z_pub_cache.c index 8c1d36221..770bf9d93 100644 --- a/examples/z_pub_cache.c +++ b/examples/z_pub_cache.c @@ -15,12 +15,6 @@ #include #include "zenoh.h" -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif int main(int argc, char **argv) { char *keyexpr = "demo/example/zenoh-c-pub"; @@ -66,7 +60,7 @@ int main(int argc, char **argv) { char buf[256]; for (int idx = 0; 1; ++idx) { - sleep(1); + z_sleep_s(1); sprintf(buf, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)buf, strlen(buf), NULL); diff --git a/examples/z_pub_shm.c b/examples/z_pub_shm.c index f26c65c08..10970bf62 100644 --- a/examples/z_pub_shm.c +++ b/examples/z_pub_shm.c @@ -17,12 +17,6 @@ #include #include "zenoh.h" -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #define N 10 @@ -85,7 +79,7 @@ int main(int argc, char **argv) { snprintf(buf, 255, "[%4d] %s", idx, value); size_t len = strlen(buf); zc_shmbuf_set_length(&shmbuf, len); - sleep(1); + z_sleep_s(1); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); z_publisher_put_options_t options = z_publisher_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); diff --git a/examples/z_pull.c b/examples/z_pull.c index d7039e902..0af23f7e2 100644 --- a/examples/z_pull.c +++ b/examples/z_pull.c @@ -12,12 +12,6 @@ // ZettaScale Zenoh Team, // #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *kind_to_str(z_sample_kind_t kind); @@ -66,7 +60,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } else { z_subscriber_pull(z_loan(sub)); } diff --git a/examples/z_query_sub.c b/examples/z_query_sub.c index 680cfd973..15564be7c 100644 --- a/examples/z_query_sub.c +++ b/examples/z_query_sub.c @@ -12,12 +12,6 @@ // ZettaScale Zenoh Team, // #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *kind_to_str(z_sample_kind_t kind); @@ -68,7 +62,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } } diff --git a/examples/z_queryable.c b/examples/z_queryable.c index f74f5d355..9d6ec7702 100644 --- a/examples/z_queryable.c +++ b/examples/z_queryable.c @@ -13,12 +13,6 @@ #include #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *expr = "demo/example/zenoh-c-queryable"; @@ -81,7 +75,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } } diff --git a/examples/z_queryable_with_channels.c b/examples/z_queryable_with_channels.c index 80c98d689..672ddd607 100644 --- a/examples/z_queryable_with_channels.c +++ b/examples/z_queryable_with_channels.c @@ -14,12 +14,6 @@ #include #include #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *expr = "demo/example/zenoh-c-queryable"; diff --git a/examples/z_scout.c b/examples/z_scout.c index 3b882f547..8dffaab7f 100644 --- a/examples/z_scout.c +++ b/examples/z_scout.c @@ -12,14 +12,6 @@ // ZettaScale Zenoh Team, #include - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif - #include "zenoh.h" void fprintpid(FILE *stream, z_id_t pid) { @@ -96,6 +88,6 @@ int main(int argc, char **argv) { z_owned_closure_hello_t closure = z_closure(callback, drop, context); printf("Scouting...\n"); z_scout(z_move(config), z_move(closure)); - sleep(1); + z_sleep_s(1); return 0; } \ No newline at end of file diff --git a/examples/z_sub.c b/examples/z_sub.c index ccfb32825..867c1277e 100644 --- a/examples/z_sub.c +++ b/examples/z_sub.c @@ -12,12 +12,6 @@ // ZettaScale Zenoh Team, // #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *kind_to_str(z_sample_kind_t kind); @@ -73,7 +67,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } } diff --git a/examples/z_sub_attachment.c b/examples/z_sub_attachment.c index 26cc95ed8..58b0afd81 100644 --- a/examples/z_sub_attachment.c +++ b/examples/z_sub_attachment.c @@ -13,12 +13,6 @@ // #include #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" const char *kind_to_str(z_sample_kind_t kind); @@ -84,7 +78,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } } diff --git a/examples/z_sub_liveliness.c b/examples/z_sub_liveliness.c index f67ac5a68..36bf64515 100644 --- a/examples/z_sub_liveliness.c +++ b/examples/z_sub_liveliness.c @@ -12,12 +12,6 @@ // ZettaScale Zenoh Team, // #include -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif #include "zenoh.h" void data_handler(const z_sample_t *sample, void *arg) { @@ -76,7 +70,7 @@ int main(int argc, char **argv) { while (c != 'q') { c = getchar(); if (c == -1) { - sleep(1); + z_sleep_s(1); } } diff --git a/examples/z_sub_thr.c b/examples/z_sub_thr.c index d32480174..05ee709d3 100644 --- a/examples/z_sub_thr.c +++ b/examples/z_sub_thr.c @@ -12,7 +12,6 @@ // ZettaScale Zenoh Team, // #include -#include #include "zenoh.h" @@ -21,46 +20,40 @@ typedef struct { volatile unsigned long count; volatile unsigned long finished_rounds; - struct timespec start; - struct timespec first_start; + z_clock_t start; + z_clock_t first_start; + bool started; } z_stats_t; z_stats_t *z_stats_make() { z_stats_t *stats = z_malloc(sizeof(z_stats_t)); stats->count = 0; stats->finished_rounds = 0; - stats->first_start.tv_nsec = 0; + stats->started = false; return stats; } -static inline double get_elapsed_s(const struct timespec *start, const struct timespec *end) { - return (double)(end->tv_sec - start->tv_sec) + (double)(end->tv_nsec - start->tv_nsec) / 1.0E9; -} - void on_sample(const z_sample_t *sample, void *context) { z_stats_t *stats = (z_stats_t *)context; if (stats->count == 0) { - clock_gettime(CLOCK_MONOTONIC, &stats->start); - if (stats->first_start.tv_nsec == 0) { + stats->start = z_clock_now(); + if (!stats->started) { stats->first_start = stats->start; + stats->started = true; } stats->count++; } else if (stats->count < N) { stats->count++; } else { - struct timespec end; - clock_gettime(CLOCK_MONOTONIC, &end); stats->finished_rounds++; - printf("%f msg/s\n", (double)N / get_elapsed_s(&stats->start, &end)); + printf("%f msg/s\n", 1000.0 * N / z_clock_elapsed_ms(&stats->start)); stats->count = 0; } } void drop_stats(void *context) { const z_stats_t *stats = (z_stats_t *)context; const unsigned long sent_messages = N * stats->finished_rounds + stats->count; - struct timespec end; - clock_gettime(CLOCK_MONOTONIC, &end); - double elapsed_s = get_elapsed_s(&stats->first_start, &end); + double elapsed_s = z_clock_elapsed_s(&stats->first_start); printf("Stats being dropped after unsubscribing: sent %ld messages over %f seconds (%f msg/s)\n", sent_messages, elapsed_s, (double)sent_messages / elapsed_s); z_free(context); diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 38f4a03ab..cafca6456 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -198,6 +198,14 @@ typedef struct z_owned_bytes_map_t { uint64_t _0[2]; size_t _1[4]; } z_owned_bytes_map_t; +/** + * Clock + * Uses monotonic clock + */ +typedef struct z_clock_t { + uint64_t t; + const void *t_base; +} z_clock_t; /** * Represents a Zenoh ID. * @@ -820,6 +828,13 @@ typedef struct z_task_t { typedef struct z_task_attr_t { size_t _0; } z_task_attr_t; +/** + * Time + * Uses system clock + */ +typedef struct z_time_t { + uint64_t t; +} z_time_t; /** * The options for `zc_liveliness_declare_token` */ @@ -1131,6 +1146,10 @@ ZENOHC_API struct z_bytes_t z_bytes_null(void); * Constructs a `len` bytes long view starting at `start`. */ ZENOHC_API struct z_bytes_t z_bytes_wrap(const uint8_t *start, size_t len); +ZENOHC_API uint64_t z_clock_elapsed_ms(const struct z_clock_t *time); +ZENOHC_API uint64_t z_clock_elapsed_s(const struct z_clock_t *time); +ZENOHC_API uint64_t z_clock_elapsed_us(const struct z_clock_t *time); +ZENOHC_API struct z_clock_t z_clock_now(void); /** * Closes a zenoh session. This drops and invalidates `session` for double-drop safety. * @@ -2010,6 +2029,9 @@ struct z_session_t z_session_loan(const struct z_owned_session_t *s); * Constructs a null safe-to-drop value of 'z_owned_session_t' type */ ZENOHC_API struct z_owned_session_t z_session_null(void); +ZENOHC_API int8_t z_sleep_ms(size_t time); +ZENOHC_API int8_t z_sleep_s(size_t time); +ZENOHC_API int8_t z_sleep_us(size_t time); /** * Returns ``true`` if `strs` is valid. */ @@ -2072,6 +2094,11 @@ int8_t z_task_init(struct z_task_t *task, void (*fun)(void *arg), void *arg); ZENOHC_API int8_t z_task_join(struct z_task_t *task); +ZENOHC_API uint64_t z_time_elapsed_ms(const struct z_time_t *time); +ZENOHC_API uint64_t z_time_elapsed_s(const struct z_time_t *time); +ZENOHC_API uint64_t z_time_elapsed_us(const struct z_time_t *time); +ZENOHC_API struct z_time_t z_time_now(void); +ZENOHC_API const char *z_time_now_as_str(const char *buf, size_t len); /** * Returns ``true`` if `ts` is a valid timestamp */ diff --git a/src/platform/clock.rs b/src/platform/clock.rs new file mode 100644 index 000000000..3f2c91c17 --- /dev/null +++ b/src/platform/clock.rs @@ -0,0 +1,131 @@ +use chrono::{DateTime, Local}; +use libc::c_char; +use std::{ + cmp::min, + os::raw::c_void, + slice, + time::{Duration, Instant, SystemTime, UNIX_EPOCH}, +}; + +use lazy_static::lazy_static; + +// Use initial time stored in static variable as a reference time, +// to be able to return number of ns passed since. +// This is to avoid wrapping Instant into a c type and not +// have to account for its platform-dependent size and alignment. +lazy_static! { + static ref CLOCK_BASE: Instant = Instant::now(); +} + +/// Clock +/// Uses monotonic clock +#[repr(C)] +#[derive(Clone, Copy)] +pub struct z_clock_t { + t: u64, + t_base: *const c_void, +} + +#[no_mangle] +pub extern "C" fn z_clock_now() -> z_clock_t { + z_clock_t { + t: CLOCK_BASE.elapsed().as_nanos() as u64, + t_base: &CLOCK_BASE as *const CLOCK_BASE as *const c_void, + } +} +#[allow(clippy::missing_safety_doc)] +unsafe fn get_elapsed_nanos(time: *const z_clock_t) -> u64 { + if time.is_null() { + return 0; + } + let now_t = (*((*time).t_base as *const CLOCK_BASE)) + .elapsed() + .as_nanos() as u64; + if now_t > (*time).t { + now_t - (*time).t + } else { + 0 + } +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_clock_elapsed_s(time: *const z_clock_t) -> u64 { + get_elapsed_nanos(time) / 1_000_000_000 +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_clock_elapsed_ms(time: *const z_clock_t) -> u64 { + get_elapsed_nanos(time) / 1_000_000 +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_clock_elapsed_us(time: *const z_clock_t) -> u64 { + get_elapsed_nanos(time) / 1_000 +} + +/// Time +/// Uses system clock +#[repr(C)] +#[derive(Clone, Copy)] +pub struct z_time_t { + t: u64, +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_time_now_as_str(buf: *const c_char, len: usize) -> *const c_char { + if len == 0 { + return buf; + } + let datetime: DateTime = SystemTime::now().into(); + let s = datetime.format("%Y-%m-%dT%H:%M:%SZ").to_string(); + let sb = s.as_bytes(); + let max_len = min(len - 1, s.len()); + let b = slice::from_raw_parts_mut(buf as *mut u8, max_len + 1); + b[0..max_len].copy_from_slice(&sb[0..max_len]); + b[max_len] = 0; + buf +} + +#[no_mangle] +pub extern "C" fn z_time_now() -> z_time_t { + z_time_t { + t: SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or(Duration::new(0, 0)) + .as_nanos() as u64, + } +} +#[allow(clippy::missing_safety_doc)] +unsafe fn get_elapsed_nanos_system_clock(time: *const z_time_t) -> u64 { + if time.is_null() { + return 0; + } + let now_t = z_time_now().t; + if now_t > (*time).t { + now_t - (*time).t + } else { + 0 + } +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_time_elapsed_s(time: *const z_time_t) -> u64 { + get_elapsed_nanos_system_clock(time) / 1_000_000_000 +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_time_elapsed_ms(time: *const z_time_t) -> u64 { + get_elapsed_nanos_system_clock(time) / 1_000_000 +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_time_elapsed_us(time: *const z_time_t) -> u64 { + get_elapsed_nanos_system_clock(time) / 1_000 +} diff --git a/src/platform/mod.rs b/src/platform/mod.rs index 3c42b831f..438763afe 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -1,5 +1,5 @@ // -// Copyright (c) 2017, 2023 ZettaScale Technology. +// Copyright (c) 2017, 2024 ZettaScale Technology. // // This program and the accompanying materials are made available under the // terms of the Eclipse Public License 2.0 which is available at @@ -12,6 +12,10 @@ // ZettaScale Zenoh team, // +pub use clock::*; +mod clock; +pub use sleep::*; +mod sleep; pub use synchronization::*; mod synchronization; diff --git a/src/platform/sleep.rs b/src/platform/sleep.rs new file mode 100644 index 000000000..b2f3e4dd7 --- /dev/null +++ b/src/platform/sleep.rs @@ -0,0 +1,19 @@ +use std::{thread, time}; + +#[no_mangle] +pub extern "C" fn z_sleep_s(time: usize) -> i8 { + thread::sleep(time::Duration::from_secs(time as u64)); + 0 +} + +#[no_mangle] +pub extern "C" fn z_sleep_ms(time: usize) -> i8 { + thread::sleep(time::Duration::from_millis(time as u64)); + 0 +} + +#[no_mangle] +pub extern "C" fn z_sleep_us(time: usize) -> i8 { + thread::sleep(time::Duration::from_micros(time as u64)); + 0 +} diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index ee63017c2..43ce08cc3 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -17,14 +17,6 @@ #undef NDEBUG #include - -#if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) -#include -#define sleep(x) Sleep(x * 1000) -#else -#include -#endif - #include "zenoh.h" #define SLEEP 1 @@ -135,7 +127,7 @@ int main(int argc, char **argv) { assert(_ret_int == -1); #endif - sleep(SLEEP); + z_sleep_s(SLEEP); size_t keyexpr_len = strlen(URI); char *keyexpr_str = (char *)z_malloc(keyexpr_len + 1); @@ -157,7 +149,7 @@ int main(int argc, char **argv) { assert(strlen(URI) == keyexpr_len); #endif - sleep(SLEEP); + z_sleep_s(SLEEP); z_owned_config_t _ret_config = z_config_new(); assert(z_check(_ret_config)); @@ -184,7 +176,7 @@ int main(int argc, char **argv) { #endif z_drop(z_move(_ret_sconfig)); - sleep(SLEEP); + z_sleep_s(SLEEP); _ret_sconfig = z_scouting_config_from(z_loan(_ret_config)); z_owned_closure_hello_t _ret_closure_hello = z_closure(hello_handler, NULL, NULL); @@ -192,8 +184,8 @@ int main(int argc, char **argv) { assert(_ret_int8 == 0); assert(hellos == 1); - sleep(atoi(SCOUTING_TIMEOUT) / 1000); - sleep(SLEEP); + z_sleep_s(atoi(SCOUTING_TIMEOUT) / 1000); + z_sleep_s(SLEEP); z_owned_session_t s1 = z_open(z_move(_ret_config)); assert(z_check(s1)); @@ -207,13 +199,13 @@ int main(int argc, char **argv) { z_owned_closure_zid_t _ret_closure_zid = z_closure(zid_handler, NULL, NULL); _ret_int8 = z_info_peers_zid(z_loan(s1), z_move(_ret_closure_zid)); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(zids == 0); _ret_int8 = z_info_routers_zid(z_loan(s1), z_move(_ret_closure_zid)); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(zids == 1); #ifdef ZENOH_PICO @@ -223,7 +215,7 @@ int main(int argc, char **argv) { zp_start_lease_task(z_loan(s1), &_ret_lease_opt); #endif - sleep(SLEEP); + z_sleep_s(SLEEP); _ret_config = z_config_default(); #ifdef ZENOH_PICO @@ -248,7 +240,7 @@ int main(int argc, char **argv) { zp_start_lease_task(z_loan(s2), NULL); #endif - sleep(SLEEP); + z_sleep_s(SLEEP); z_session_t ls1 = z_loan(s1); z_owned_closure_sample_t _ret_closure_sample = z_closure(data_handler, NULL, &ls1); @@ -257,7 +249,7 @@ int main(int argc, char **argv) { z_declare_subscriber(z_loan(s2), z_keyexpr(keyexpr_str), z_move(_ret_closure_sample), &_ret_sub_opt); assert(z_check(_ret_sub)); - sleep(SLEEP); + z_sleep_s(SLEEP); char s1_res[64]; sprintf(s1_res, "%s/chunk/%d", keyexpr_str, 1); @@ -271,14 +263,14 @@ int main(int argc, char **argv) { _ret_int8 = z_put(z_loan(s1), z_loan(_ret_expr), (const uint8_t *)value, strlen(value), &_ret_put_opt); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(datas == 1); z_delete_options_t _ret_delete_opt = z_delete_options_default(); _ret_int8 = z_delete(z_loan(s1), z_loan(_ret_expr), &_ret_delete_opt); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(datas == 2); _ret_int8 = z_undeclare_keyexpr(z_loan(s1), z_move(_ret_expr)); @@ -303,23 +295,23 @@ int main(int argc, char **argv) { _ret_int8 = z_publisher_put(z_loan(_ret_pub), (const uint8_t *)value, strlen(value), &_ret_pput_opt); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); _ret_int8 = z_subscriber_pull(z_loan(_ret_psub)); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(datas == 3); z_publisher_delete_options_t _ret_pdelete_opt = z_publisher_delete_options_default(); _ret_int8 = z_publisher_delete(z_loan(_ret_pub), &_ret_pdelete_opt); - sleep(SLEEP); + z_sleep_s(SLEEP); _ret_int8 = z_subscriber_pull(z_loan(_ret_psub)); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(datas == 4); _ret_int8 = z_undeclare_publisher(z_move(_ret_pub)); @@ -328,7 +320,7 @@ int main(int argc, char **argv) { _ret_int8 = z_undeclare_pull_subscriber(z_move(_ret_psub)); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); z_owned_closure_query_t _ret_closure_query = z_closure(query_handler, NULL, &ls1); z_queryable_options_t _ret_qle_opt = z_queryable_options_default(); @@ -336,7 +328,7 @@ int main(int argc, char **argv) { z_declare_queryable(z_loan(s1), z_keyexpr(s1_res), z_move(_ret_closure_query), &_ret_qle_opt); assert(z_check(qle)); - sleep(SLEEP); + z_sleep_s(SLEEP); z_session_t ls2 = z_loan(s2); z_owned_closure_reply_t _ret_closure_reply = z_closure(reply_handler, NULL, &ls2); @@ -350,7 +342,7 @@ int main(int argc, char **argv) { _ret_int8 = z_get(z_loan(s2), z_keyexpr(s1_res), "", z_move(_ret_closure_reply), &_ret_get_opt); assert(_ret_int8 == 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert(queries == 1); assert(replies == 1); @@ -372,7 +364,7 @@ int main(int argc, char **argv) { _ret_int8 = z_close(z_move(s2)); assert(_ret_int8 == 0); - sleep(SLEEP * 5); + z_sleep_s(SLEEP * 5); z_free(keyexpr_str); diff --git a/tests/z_int_pub_cache_query_sub_test.c b/tests/z_int_pub_cache_query_sub_test.c index 6674aec55..82c27b97f 100644 --- a/tests/z_int_pub_cache_query_sub_test.c +++ b/tests/z_int_pub_cache_query_sub_test.c @@ -122,7 +122,7 @@ int run_subscriber() { } SEM_POST(sem_sub); - sleep(10); + z_sleep_s(10); z_drop(z_move(sub)); z_close(z_move(s)); diff --git a/tests/z_int_pub_sub_attachment_test.c b/tests/z_int_pub_sub_attachment_test.c index 75ae88547..c7f502a59 100644 --- a/tests/z_int_pub_sub_attachment_test.c +++ b/tests/z_int_pub_sub_attachment_test.c @@ -106,7 +106,7 @@ int run_subscriber() { } SEM_POST(sem); - sleep(10); + z_sleep_s(10); z_undeclare_subscriber(z_move(sub)); z_close(z_move(s)); diff --git a/tests/z_int_queryable_attachment_test.c b/tests/z_int_queryable_attachment_test.c index b2f2a7ab8..ce1ac9f42 100644 --- a/tests/z_int_queryable_attachment_test.c +++ b/tests/z_int_queryable_attachment_test.c @@ -76,7 +76,7 @@ int run_queryable() { } SEM_POST(sem); - sleep(10); + z_sleep_s(10); z_drop(z_move(qable)); z_close(z_move(s)); diff --git a/tests/z_int_queryable_test.c b/tests/z_int_queryable_test.c index 4244af2c7..2999451c4 100644 --- a/tests/z_int_queryable_test.c +++ b/tests/z_int_queryable_test.c @@ -59,7 +59,7 @@ int run_queryable() { } SEM_POST(sem); - sleep(10); + z_sleep_s(10); z_drop(z_move(qable)); z_close(z_move(s));